How to make custom DataGridViewComboBox dependent only on its DataGridViewComboBoxColumn?

旧时模样 提交于 2020-01-02 16:23:28

问题


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)
    }
}

回答1:


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..



来源:https://stackoverflow.com/questions/31466145/how-to-make-custom-datagridviewcombobox-dependent-only-on-its-datagridviewcombob

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!