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

How to make custom DataGridViewComboBox dependent only on its DataGridViewComboBoxColumn?

流行方式(1, 2) DataGridViewComboBox 中项目的自定义绘制是处理事件 DataGridView1。EditingControlShowing 并在那里设置 DrawItem 事件处理程序:

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

你看出了什么问题:它使用控制级事件来处理列的工作。但是,如果我有 50 多个数据网格视图怎么办?自定义组合框的绘制应按列实例处理,保持控件级别不变。

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

(要重现,只需将以下内容粘贴到 class 文件中并将类型为 DataGridViewCustomPaintComboBoxColumn 的列添加到您的 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)
    }
}

我遇到的唯一问题是未调用 OnDrawItem() 方法。我错过了什么?

您在聚焦的 DataGridViewComboBoxCell 中看到的几乎是一个 'real' ComboBox,您需要引用它才能挂接到它的 DrawItem 事件! (您可以查看 DGV 的 Controls 集合,看看当 ComboBoxCell 具有焦点时还有一个。DataGridViewComboBoxEditingControl 直接来自 ComboBox

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

看来你缺的就是这个!

如果您可以创建自己的 DataGridViewComboBoxEditingControl 并让它出现在您的 DGV 中,那么您就大功告成了。


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

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

在注册函数中,它会挂钩到必要的 DGV 方法中,即 EditingControlShowing 以获取您看到的 ComboBox,当 DGV 具有焦点并且 CellPainting 用于其他情况。

装饰器可以是静态的,您注册的所有列只需要一个 ComboBox,因为一次只有一个可以有焦点..

如果你能在装饰器中处理所有的绘画代码就更好了。从事件中,它总是可以通过 sender 返回到 DataGridView 并通过 DataGridViewCellPaintingEventArgs 参数返回到单元格的属性..

您甚至可以将对当前单元格的引用放入 ComboBox 引用的 Tag:

theBoxCell.Tag = dataGridView1.CurrentCell;

如果您愿意,您还可以提供个人代表在注册时调用绘画事件。然后你必须保留这些列表,也许在字典中..