在工作中,需要自定义DataGridView中承载的控件,就简单地学习了一下,上篇文章把DGV中简单的一些用法,包括“非绑定”方式的填充和“绑定”方式的填充数据方式介绍了一下,还简单介绍了更改列的显示内容的情况,这篇主要介绍如何让DGV能够承载自定义控件的情况,应该来讲,对于我这种WINFORM菜鸟来讲,这部分内容还是有点难度的,MSDN上的相关介绍是这篇文章的主要参考,具体地址是这里
简单地介绍下我想实现的效果,首先扩展系统自带的ComboBox控件,让它自动地加载系统定义的颜色,然后在DGV中利用该控件来完成拾取颜色的功能,最终实现的效果如下图所示,左图是DGV加载后的效果,右图为进入拾取颜色状态时的效果.
废话不多说,下来马上来一步步地实现这个例子。第一步,我们要通过扩展ComboBox来实现加载系统自定义颜色的ComboBox控件,这步是比较简单的,直接上代码:
/// <summary>
/// An example to customize control in datagridview
/// </summary>
class CustomComboBox: ComboBox
{
#region constructor
public CustomComboBox()
: base()
{
this.DrawMode = DrawMode.OwnerDrawFixed; //要把模式调成用户自行绘制的模式,否则没有效果
this.DropDownStyle = ComboBoxStyle.DropDownList; //下拉列表风格,用户无法编辑列表内容
addColors();
}
private void addColors()
{
//add colors
Items.Clear();
Array colors = System.Enum.GetNames(typeof(KnownColor)); //这里有两种方法,getNames和getValues,有细微的区别
foreach (object obj in colors)
Items.Add(obj);
}
#endregion
#region override function
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (e.Index < 0) return;
Rectangle rect = e.Bounds;
rect.Inflate(-2, -2);
Color color=Color.FromName(Items[e.Index] as String);
Brush brush=new SolidBrush(color);
Random random = new Random();
//很简陋的取“反色”的方式来显示文字
Brush brushForString = new SolidBrush(Color.FromArgb(255 - color.R,255 - color.G,255 - color.B));
e.Graphics.DrawRectangle(Pens.Black, rect);
e.Graphics.FillRectangle(brush, rect);
e.Graphics.DrawString(Items[e.Index] as String, e.Font, brushForString, rect.Location);
}
#endregion
在构造函数中,我们调用addColors方法加载了系统自定义的所有颜色,然后重载onDrawItem来自定义列表的外观,这样一个定制的控件就完成了,还是比较轻松的。
接下来我们就要在DGV中使用这个控件了,查阅MSDN的文档可以看到,如果要让DGV能够承载自定义控件,要完成以下的事情:
1. 自定义控件,并且该控件要实现IDataGridViewEditingControl接口
2.继承DataGridViewCell类,并重载InitializeEditingControl方法,在方法中实现承载控件的初始化和赋值操作
3. 继承DataGridViewColumn类,使用继承的DataGridViewCell类作为模板
在我们实现这些步骤之前,有一个操作上的逻辑还是有必要明确一下,当DGV的表格中使用编辑控件时,当用户点击单元格时,DGV就会调用该单元格所在列DataGridViewColumn的单元格模板,也就是DataGridViewCell中的InitializeEditingControl方法,在这个方法中,把显示在单元格上的值(AKA:Cell value)转化成编辑控件的值,而显示在编辑控件上的值也被称为FormattedValue,用户通过编辑控件修改值以后,会通过DataGridViewCell的ParseFormattedValue方法将FormattedValue转化成CellValue,同时退出编辑状态.我认为这个操作逻辑可能是在学习并实现DGV承载自定义控件过程中最模糊也最重要的一个点,理解这个过程对于实现IDataGridViewEditingControl接口中各种方法的意义有很直接的作用。
好了,我们首先来完成CustomComboBox的IDataGridViewEditingControl接口实现,代码如下,哦,对了,不要忘了在CustomComboBox的后面加上接口声明:
#region IDataGridViewEdtingControl Interface
// Summary:
// Gets or sets the System.Windows.Forms.DataGridView that contains the cell.
//
// Returns:
// The System.Windows.Forms.DataGridView that contains the System.Windows.Forms.DataGridViewCell
// that is being edited; null if there is no associated System.Windows.Forms.DataGridView.
// 用来指示该控件的宿主DGV控件
p