【问题标题】:How to make custom DataGridViewComboBox dependent only on its DataGridViewComboBoxColumn?如何使自定义 DataGridViewComboBox 仅依赖于其 DataGridViewComboBoxColumn?
【发布时间】:2015-10-06 14:29:07
【问题描述】:

流行方式 (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 多个 datagridviews 怎么办?应按列实例处理自定义组合框的绘制,保持控制级别不变。

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

(要重现,只需将以下内容粘贴到类文件中,并将 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)
    }
}

【问题讨论】:

    标签: .net winforms events datagridviewcolumn datagridviewcombobox


    【解决方案1】:

    我唯一的问题是 OnDrawItem() 方法没有被调用。我错过了什么?

    您在集中的DataGridViewComboBoxCell 中看到的内容几乎是“真实的”ComboBox,您需要对其进行引用才能挂钩其DrawItem 事件! (您可以查看 DGV 的 Controls 集合,看看当 ComboBoxCell 具有焦点时还有一个集合。DataGridViewComboBoxEditingControl 直接来自 ComboBox

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

    看起来这就是你所缺少的!

    如果您可以创建自己的 DataGridViewComboBoxEditingControl 并将其显示在您的 DGV 中,那么您就大功告成了。


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

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

    在注册功能中,它会挂接到必要的 DGV 方法,即 EditingControlShowing 在 DGV 具有焦点时获取您看到的 ComboBox,而在其他情况下使用 CellPainting

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

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

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

    theBoxCell.Tag = dataGridView1.CurrentCell;
    

    如果您愿意,您还可以在注册时提供单独的代表来调用绘制事件。然后,您必须保留这些列表,可能在字典中..

    【讨论】:

    • 我了解您的静态装饰器想法,但在接受答案之前,我不确定您的推理。正如您所说,DataGridViewComboBoxCell 不是控件。它用于在非活动单元格中绘制控件的副本(并将单个控件实例提供给已编辑的单元格)。因此,覆盖其OnPaint() 事件按预期工作(我扩展了上述来源)。 OTOH DataGridViewComboBoxEditingControl 一个控件(ComboBox 的直接后代),所以当它的实例被创建用于EditingControlShowing 事件时,它被覆盖的OnPaint()ItemDraw() 应该可以工作,不是吗?
    • 是的,我想你没问题,除了我不确定 Paint/OnPaint 事件是否会生效甚至触发;它们被 DrawItem/OnDrawItem 事件所取代。要绘制未删除的部分,您需要检查e.Index == -1
    • 目前我不确定我们的想法是否正确。我需要重申。我的观点:第一:reference source for DataGridViewComboBoxEditingControl.cs 确实 not 显示其 ComboBox 前任的任何操作。(不禁用绘画等)第二:覆盖 OnPaint()OnDrawItem() 确实 即使使用标准的普通ComboBox 也不能工作。因此,也许在发现如何正确创建自定义绘制的组合框之后,可能不需要装饰器 - 只需正确编写 DataGridViewComboBoxEditingControl 的后代 :)。让我检查一下...
    • 重写 OnPaint() 和 OnDrawItem() 即使使用标准的普通 ComboBox 也不起作用。嗯, OnPaint 我不希望工作,它甚至没有显示在设计器或 Intellisense 中。但是 OnDrawItem?? (您确实将其 DrawMode 设置为某个 OwnerDrawXxx ?)
    • 我忘记设置 DrawMode!似乎它解决了这一切:) OnDrawItem() 现在被调用,所以我可以做任何我需要的事情。将此作为您的答案,我会接受。也许忘记所有静态装饰器的东西,它对自定义绘画没有附加价值。所以我会接受你的回答:只需将DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed(或OwnerDrawVariable)添加到DataGridViewComboBoxEditingControl构造函数中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2021-04-27
    • 2015-07-03
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2022-08-15
    相关资源
    最近更新 更多