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