.net 如何使自定义DataGridViewComboBox仅依赖于其DataGridViewComboBox列?

.net 如何使自定义DataGridViewComboBox仅依赖于其DataGridViewComboBox列?,.net,winforms,events,datagridviewcolumn,datagridviewcombobox,.net,Winforms,Events,Datagridviewcolumn,Datagridviewcombobox,流行方式(,) 对于DataGridViewComboBox中项目的自定义绘制,它处理事件DataGridView1。编辑控件显示并在其中设置DrawItem事件处理程序: private void dataGridView1_EditingControlShowing( object sender, DataGridViewEditingControlShowingEventArgs e) { theBoxCell = (ComboBox) e.Control;

流行方式(,) 对于DataGridViewComboBox中项目的自定义绘制,它处理事件DataGridView1。编辑控件显示并在其中设置DrawItem事件处理程序:

private void dataGridView1_EditingControlShowing(
    object sender,
    DataGridViewEditingControlShowingEventArgs e)
{
    theBoxCell = (ComboBox) e.Control;
    theBoxCell.DrawItem += theBoxCell_DrawItem;
    theBoxCell.DrawMode = DrawMode.OwnerDrawVariable;
}
您可以看到问题所在:它使用控件级事件来处理列的工作。但是如果我有50多个DataGridView呢?自定义组合框的绘制应按列实例处理,保持控制级别不变

每列处理的最低实现如下所示。我唯一的问题是没有调用
OnDrawItem()
方法。我错过了什么?(您可以看到来自同一类的紫红色背景覆盖正在工作。)

(要复制,只需将以下内容粘贴到类文件中,并将类型为DataGridViewCustomPaintComboxColumn的列添加到您的DataGridView1

公共类DataGridViewCustomPaintComboxColumn:DataGridViewComboxColumn
{
公共DataGridViewCustomPaintComboxColumn()
{
base.New();
CellTemplate=新的DataGridViewCustomPaintComboxCell();
}
}
公共类DataGridViewCustomPaintComboxCell:DataGridViewComboxCell
{
公共覆盖类型EditType{
获取{return typeof(DataGridViewCustomPaintComboxeditingControl);}
}
受保护的覆盖无效绘制(…)
{
//在这里为细胞涂鸦——效果很好
}
}
公共类DataGridViewCustomPaintComboxeditingControl:DataGridViewComboxeditingControl
{
公共覆盖颜色背景色{//仅用于测试的属性覆盖
获取{return Color.Fuchsia;}//测试值按预期工作
设置{base.BackColor=value;}
}
受保护的覆盖void OnPaint(PaintEventArgs e)//从未调用-为什么?
{
基础漆(e)
}
受保护的覆盖void OnDrawItem(DrawItemEventArgs e)//从未调用-为什么?
{
基本项目(e)
}
}
我唯一的问题是没有调用OnDrawItem()方法。我错过了什么

您在聚焦的
DataGridViewComboBoxCell
中看到的几乎是一个“真实的”
ComboBox
,您需要一个对它的引用才能连接到它的
DrawItem
事件中!(您可以查看DGV的控件集合,以查看ComboBox单元格具有焦点时是否还有一个控件。
DataGridViewComboBox编辑控件
直接从
ComboBox
派生)

注意:与开箱即用的
CombBox
的一个区别在于,它默认设置了
DrawMode=OwnerDrawVariable
。如果您想用自己创建的东西来替换它,请不要忘记在代码中设置它

看来这就是你所缺少的

如果您可以创建自己的
DataGridViewComboBoxEditingControl
并将其显示在DGV中,则一切就绪


我经常使用的另一种模型是一种“Decorator”,它为您注册的所有列实现自定义绘图

DgvCombBoxPainter.Register(DataGridView dgv, stringOrInt columnNameOrIndex..)
在注册函数中,它将连接到必要的DGV方法中,即当DGV具有焦点并且对于其他情况使用了
CellPaint
时,即
EditingControlShowing
,以获得您看到的
组合框

装饰器可以是静态的,并且对于您注册的所有列只需要一个
组合框
,因为一次只能有一个焦点

如果你能在decorator中更好地处理所有的绘画代码。从事件中,它始终可以通过
sender
返回到
DataGridView
,并通过
DataGridViewCellPaintingEventArgs
参数返回单元格属性

您甚至可以将当前单元格的引用放入
组合框
引用的
标记

theBoxCell.Tag = dataGridView1.CurrentCell;

如果需要,还可以提供单个代理,以便在注册时调用绘制事件。然后,您必须保留一个列表,可能在字典中。

我理解您的静态装饰器想法,但在接受答案之前,我不确定您的推理。正如您所说,
DataGridViewComboxCell
不是控件。它用于在非活动单元格中绘制控件的副本(并将单个控件实例提供给已编辑的单元格)。因此,重写其
OnPaint()
事件的效果与预期一样(我扩展了上述源代码)。OTOH
DataGridViewComboBoxEditingControl
是一个控件(ComboBox
的直接后代),因此当创建它的实例用于
EditingControlShowing
事件时,它被重写的
OnPaint()
ItemDraw()
应该可以工作,不是吗?是的,我想你已经搞定了,除了我不确定油漆/油漆事件是否会生效,甚至不会着火;它们被DrawItem/OnDrawItem事件替换。要画出没有掉下来的部分,你需要检查
e.Index==-1
。目前我不确定我们的思路是否正确。我需要重申。我的观点:第一:使用它的
组合框
前置器不显示任何操作(不禁用绘画内容等)。第二:覆盖
OnPaint()
OnDrawItem()
即使使用标准的普通
组合框
,也不起作用。因此,在发现如何正确创建自定义绘制的组合框后,可能不需要任何装饰程序–只需要正确编写的
datagridviewcomboxeditingcontrol
:)的后代。让我检查一下……重写OnPaint()和OnDrawItem()即使对于标准的普通组合框也不起作用。嗯,OnPaint我不希望工作,它甚至没有在designer或Intellisense中显示。但是我的项目呢??(您确实将其DrawMode设置为某个OwnerDrawXxx?)我忘记设置DrawMode了!它似乎解决了所有问题:)
OnDrawItem()
现在被调用了,所以我可以做w