65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 Windows Forms DataGridView 单元格中托管颜色选择器组合框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (30投票s)

2008年3月24日

CPOL

3分钟阅读

viewsIcon

199321

downloadIcon

12807

一篇关于如何向 DataGridView 添加颜色选择器 ComboBox 的文章。

引言

.NET Framework 为 WinForms 开发提供了相当丰富的 UI 控件和组件。但是,有一个特别的控件一直缺失。我说的是一个具有下拉颜色选择功能的颜色选择器控件,就像 Visual Studio .NET 属性浏览器中用于编辑 Color 类型属性的那个。

Palo Mraz 开发了一个颜色选择器控件,并在此网站上发布。我想在 DataGridView 中使用这个控件,但我找不到任何相关的示例。唯一可用的关于如何在 DataGridView 中使用自定义控件的示例都与文本控件有关。这个自定义控件涉及图形,而不仅仅是文本。我决定发布这篇文章,以造福其他希望在 DataGridView 中承载颜色选择器组合框的开发者。

背景

对于那些想了解颜色选择器组合框背景的读者,请参考“ColorPicker WinForms 控件”。

您可以在 这里 获取有关如何在 DataGridView 单元格中承载自定义控件的背景信息。

DataGridView 中的颜色选择器

我的项目的核心需求是在 DataGridView 中显示 WinForm 的 PropertyGrid 控件中使用的下拉颜色选择器。

DataGridView 控件提供了几个属性,您可以使用它们来调整其单元格、行和列的外观和基本行为(外观)。我的需求是显示颜色本身,旁边显示颜色的名称。

为了实现这一点,我不得不为控件实现所有者绘制,并通过创建自定义单元格、列和行来扩展其功能。

ColorPickerColumn 类

此类创建一个自定义列,用于承载一列颜色选择器单元格。它继承自 DataGridViewColumn,并重写了 CellTemplate 属性。

public override DataGridViewCell CellTemplate
{
    get
    {
        return base.CellTemplate;
    }
    set
    {
        // Ensure that the cell used for the template is a ColorPickerCell.
        if (value != null && 
            !value.GetType().IsAssignableFrom(typeof(ColorPickerCell)))
        {
            throw new InvalidCastException("Must be a ColorPicker");
        }
        base.CellTemplate = value;
    }
}

ColorPickerCell 类

此类创建一个自定义单元格,用于承载颜色选择器组合框,它继承自 DataGridViewTextBoxCell。为了以我想要的方式绘制单元格的内容,我重写了 paint 方法。

 protected override void Paint(Graphics graphics,
           Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
           DataGridViewElementStates elementState, object value,
           object formattedValue, string errorText,
           DataGridViewCellStyle cellStyle,
           DataGridViewAdvancedBorderStyle advancedBorderStyle,
           DataGridViewPaintParts paintParts)
{
    formattedValue = null;
    
    base.Paint(graphics, clipBounds, cellBounds, rowIndex, 
            elementState, value, formattedValue,
               errorText, cellStyle, advancedBorderStyle, paintParts);

   
    Rectangle ColorBoxRect = new Rectangle();
    RectangleF TextBoxRect = new RectangleF();
    GetDisplayLayout(cellBounds, ref ColorBoxRect, ref TextBoxRect);

    /// Draw the cell background, if specified.
    if ((paintParts & DataGridViewPaintParts.Background) ==
        DataGridViewPaintParts.Background)
    {
        SolidBrush cellBackground;
        if (value != null && value.GetType() == typeof(Color))
        {
            cellBackground = new SolidBrush((Color)value);
        }
        else
        {
            cellBackground =  new SolidBrush(cellStyle.BackColor);
        }
        graphics.FillRectangle(cellBackground, ColorBoxRect);
        graphics.DrawRectangle(Pens.Black, ColorBoxRect);
        Color lclcolor=(Color)value;
        graphics.DrawString(lclcolor.Name.ToString(), cellStyle.Font, 
            System.Drawing.Brushes.Black, TextBoxRect);
    
        cellBackground.Dispose();
    }
}

我不得不重写的另一个方法是 ParseFormattedValue。当用户从列表中选择自定义颜色时,他/她会获得该颜色的十六进制数字。这个数字有一个小问题:它没有添加 0x 前缀。这会导致 System.Number.StringToNumber 方法生成异常。.NET 环境尝试将此 string 转换为整数,但由于没有 0x 前缀,它无法被视为十六进制数字,因此此方法在需要时添加前缀。

public override object ParseFormattedValue
    object formattedValue, DataGridViewCellStyle cellStyle, 
         System.ComponentModel.TypeConverter formattedValueTypeConverter, 
         System.ComponentModel.TypeConverter valueTypeConverter)
{
    int result;
    string number = "0x" + formattedValue.ToString();
    if (int.TryParse(formattedValue.ToString(), 
        stem.Globalization.NumberStyles.HexNumber, null, out result))
        //Hex number
        return base.ParseFormattedValue("0x" + formattedValue.ToString(), 
            lStyle, formattedValueTypeConverter, valueTypeConverter);
    else
        return base.ParseFormattedValue(formattedValue, cellStyle, 
            mattedValueTypeConverter, valueTypeConverter);
}

ColorPickerControl 类

此类创建要由 ColorPickerCell 承载的自定义控件。它实现了 IDataGridViewEditingControl 接口,并重写了原始 ColorPicker 控件的 OnLeave 事件。OnLeave – 此事件调用 NotifyDataGridViewOfValueChange 来通知 DataGridView 单元格的内容已更改。

protected override void OnLeave(EventArgs eventargs)
{
    // Notify the DataGridView that the contents of the cell
    // have changed.
    base.OnLeave(eventargs);
    NotifyDataGridViewOfValueChange();
}

Using the Code

我创建了一个名为 ExampleForm 的窗体,其中包含一个 DataGridView 控件。该网格有两个列:第一列是简单的 textbox 列,第二列是 ColorPicker 列。在此窗体中,我演示了如何将包含颜色和名称的数据加载和保存到名为 ColorData.xml 的 XML 文件中,以及如何从该文件中加载。该文件应存储在可执行文件的同一文件夹中。

历史

  • 2008 年 3 月 25 日:首次发布

关于作者

我住在新西兰。过去 6 年我一直在从事 Microsoft Windows 开发。

© . All rights reserved.