如何使自定义DataGridViewComboBox只依赖于它的DataGridViewComboBoxColumn?它的、自定义、依赖于、DataGridViewComboBoxColumn

2023-09-07 08:48:47 作者:御姐

流行的方式( 1 , 2 ) 在项目的风俗画的 DataGridViewComboBox 正在处理事件dataGridView1的的 EditingControlShowing 并建立DRAWITEM事件处理程序有:

 私人无效dataGridView1_EditingControlShowing(
    对象发件人,
    DataGridViewEditingControlShowingEventArgs五)
{
    theBoxCell =(组合框)e.Control;
    theBoxCell.DrawItem + = theBoxCell_DrawItem;
    theBoxCell.DrawMode = DrawMode.OwnerDrawVariable;
}
 

您看到什么是错的:它使用的控件级别的事件的处理列的工作。但是,如果我有50多个datagridviews?自定义组合框画应的每列例如的处理,使控制水平不变。

最小的实现,每列的处理如下。唯一的问题我已经是的OnDrawItem()方法不获取调用。我在想什么? (你可以看到从紫红色的背景覆盖的一样的类工作。)

(复制,只需键入以下成class文件,并添加列 DataGridViewCustomPaintComboBoxColumn 粘贴到您的 dataGridView1的。)

公共类DataGridViewCustomPaintComboBoxColumn:DataGridViewComboBoxColumn {     公共DataGridViewCustomPaintComboBoxColumn()     {         base.New();         CellTemplate =新DataGridViewCustomPaintComboBoxCell();     } } 公共类DataGridViewCustomPaintComboBoxCell:的DataGridViewComboBoxCell {     公众覆盖类型EditType {         {返回的typeof(DataGridViewCustomPaintComboBoxEditingControl); }     }     保护覆盖无效油漆(...)     {         //画的东西在这里incative细胞 - 效果很好     } } 公共类DataGridViewCustomPaintComboBoxEditingControl:DataGridViewComboBoxEditingControl {     公众覆盖色背景色{//属性重写仅用于测试         {返回Color.Fuchsia; } //测试值按预期工作         集合{base.BackColor =价值; }     }     保护覆盖无效的OnPaint(PaintEventArgs的E)//从来没有所谓的 - 为什么?     {         base.OnPaint(五)     }     保护覆盖无效的OnDrawItem(DrawItemEventArgs E)//从来没有所谓的 - 为什么?     {         base.OnDrawItem(五)     } }

解决方案

唯一的问题我已经是的OnDrawItem()方法是没有得到调用。我在想什么?的

你里面看到一个集中的DataGridViewComboBoxCell 是pretty的多少真正的组合框,你需要对它的引用,以挂钩到其 DRAWITEM 活动! (你可以有一个看看DGV的控件集合地看到,还有一个当ComboBoxCell具有焦点.. DataGridViewComboBoxEditingControl 是直接从下降组合框

QQ使用自定义头像权限

注意:一个差的开箱即用 CombBox 是已成立 DrawMode = OwnerDrawVariable 默认情况下。如果你想通过自己创建的东西来取代它,不要忘了将它设置在code!

貌似这是你错过了什么!

如果你可以创建自己的 DataGridViewComboBoxEditingControl 并使其出现在DGV你所有的设置。

这是另一种模式,我经常用的是一种装饰,即实现了您注册它的所有列的自定义绘制的。

  DgvCombBoxPainter.Register(DataGridView中DGV,stringOrInt columnNameOrIndex ..)
 

在注册功能将钩到必要的DGV的方法,那就是 EditingControlShowing 获得的组合框你看,当DGV具有焦点和 CellPainting 的其他情况。

装饰器可以是静态的,只需要一个组合框所有已注册的列,因为只有一个可以有重点的时间。

如果你能处理所有的绘画code的装饰就更好了。从事件它可以随时通过 DataGridViewCellPaintingEventArgs 参数。

您甚至可以把一个引用当前单元格到组合框引用的标签

  theBoxCell.Tag = dataGridView1.CurrentCell;
 

如果你愿意,你也可以提供个人代表在内线活动事件的注册时调用

。然后,您就必须保持这些列表,也许在一个字典。

Popular way (1, 2) for custom painting of items in DataGridViewComboBox is handling of event DataGridView1.EditingControlShowing and setting up DrawItem event handlers there:

private void dataGridView1_EditingControlShowing(
    object sender,
    DataGridViewEditingControlShowingEventArgs e)
{
    theBoxCell = (ComboBox) e.Control;
    theBoxCell.DrawItem += theBoxCell_DrawItem;
    theBoxCell.DrawMode = DrawMode.OwnerDrawVariable;
}

You see what is wrong: it uses control-level event to handle work for columns. But what if I have 50+ datagridviews? Painting of custom combo boxes should be handled per column instance, leaving control level intact.

Minimal implementation of per-column handling is below. The only problem I have is that OnDrawItem() method is not getting called. What am I missing? (You can see that fuchsia background override from the same class is working.)

(To reproduce, just paste the following into class file and add column of type DataGridViewCustomPaintComboBoxColumn to your DataGridView1.)

public class DataGridViewCustomPaintComboBoxColumn : DataGridViewComboBoxColumn
{
    public DataGridViewCustomPaintComboBoxColumn()
    {
        base.New();
        CellTemplate = new DataGridViewCustomPaintComboBoxCell();
    }

}

public class DataGridViewCustomPaintComboBoxCell : DataGridViewComboBoxCell
{
    public override Type EditType {
        get { return typeof(DataGridViewCustomPaintComboBoxEditingControl); }
    }

    protected override void Paint(...)
    {
        //painting stuff for incative cells here - works well
    }

}

public class DataGridViewCustomPaintComboBoxEditingControl : DataGridViewComboBoxEditingControl
{
    public override Color BackColor { // property override only for testing
        get { return Color.Fuchsia; }    // test value works as expected
        set { base.BackColor = value; }
    }

    protected override void OnPaint(PaintEventArgs e) // never called - why?
    {
        base.OnPaint(e)
    }

    protected override void OnDrawItem(DrawItemEventArgs e)  // never called - why?
    {
        base.OnDrawItem(e)
    }
}

解决方案

The only problem I have is that OnDrawItem() method is not getting called. What am I missing?

What you see inside a focussed DataGridViewComboBoxCell is pretty much a 'real' ComboBox and you need a reference to it in order to hook into its DrawItem event! (You can have a look the Controls collection of the DGV to see that there is one more when a ComboBoxCell has focus.. DataGridViewComboBoxEditingControl is directly descended from ComboBox )

Note: One difference to an out of the box CombBox is that is has set DrawMode = OwnerDrawVariable by default. If you want to replace it by something you create yourself, don't forget to set it in code!

Looks like that is what you are missing!

If you can create your own DataGridViewComboBoxEditingControl and make it appear in your DGV you're all set.

An alternative model I often use is a sort of 'Decorator', that implements the custom drawing for all columns you register with it.

DgvCombBoxPainter.Register(DataGridView dgv, stringOrInt columnNameOrIndex..)

In the registration function it would hook into the necessary DGV methods, that is EditingControlShowing to get at the ComboBox you see, when the DGV has focus and the CellPainting for the other cases.

The decorator can be static and needs only one ComboBox for all columns you have registered, as only one can have focus at a time..

If you can handle all painting code in the decorator all the better. From the events it can always reach back to the DataGridView via sender and the cells' properties via the DataGridViewCellPaintingEventArgs parameter..

You can even put a reference to the current cell into the ComboBox reference's Tag:

theBoxCell.Tag = dataGridView1.CurrentCell;

If you want you could also provide individual delegates to call in the paint event(s) when registering. You would then have to keep a list of those, maybe in a Dictionary..