如何在 DataGridViewComboBox 列中绘制非活动行?

Posted

技术标签:

【中文标题】如何在 DataGridViewComboBox 列中绘制非活动行?【英文标题】:How to paint inactive rows in DataGridViewComboBox column? 【发布时间】:2015-07-16 11:30:22 【问题描述】:

我可以easily paint items in DataGridViewComboBox dropdown list。但我不知道如何在同一列中绘制非活动单元格

我已经看过、研究并尝试了许多经典 ComboBox 的示例,但我并不了解 DataGridViewComboBox 的所有方面。

目前我有从 DataGridViewComboBox 派生的 DataGridViewCustomPaintComboBox 类。要提供的最小覆盖集是多少?你能指出我正确的方向吗?

【问题讨论】:

【参考方案1】:

在没有焦点的情况下绘制非活动单元格所需的最小值似乎是CellTemplate 分配和Paint() 覆盖:

public class DataGridViewCustomPaintComboBox : DataGridViewComboBoxColumn


    public DataGridViewCustomPaintComboBox()
    
        base.New();
        CellTemplate = new DataGridViewCustomPaintComboBoxCell();
    



public class DataGridViewCustomPaintComboBoxCell : DataGridViewComboBoxCell


    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    
        // modify received arguments here
        base.Paint(...); // paint default parts (see paintParts argument)
        // add any custom painting here

    


【讨论】:

【参考方案2】:

更新

自定义绘制DataGridViewComboBox 有点复杂。实际上它由四种不同的绘图案例组成:

对于未聚焦的单元格,您需要编写CellPainting 事件:

private void dataGridView1_CellPainting(object sender, 
                                        DataGridViewCellPaintingEventArgs e)

   // drawstuff nr 1: draw the unfocused cell

当单元格具有焦点时,实际的DataGridViewComboBoxEditingControl(它是ComboBox 的直接后代)被创建并显示。

您需要获取它的句柄(在 EditingControlShowing 事件中),然后应该在其 DrawItem 事件中再编写三个案例:

void theBoxCell_DrawItem(object sender, DrawItemEventArgs e)

    if (e.Index < 0)
    
       // drawstuff 2: draw the undropped top portion
    
    else
    
       if ((e.State & DrawItemState.Selected) != DrawItemState.None
       
          // drawstuff 3:  draw a selected item
       
       else
       
          // drawstuff 4:  draw an unselected item   
       
    
 

关于各种油漆代码的几点说明:

drawstuff 1:在这里您应该在绘制文本后绘制一个箭头。为此,最好使用ComboBoxRenderer.DrawDropDownButton 方法。您需要知道位置和大小,SystemInformation.VerticalScrollBarWidth 应该对此有所帮助。请注意,TextRenderer.DrawText 不仅可以让您使用漂亮的TextFormatFlags 来帮助对齐,还可以使用Backcolor

drawstuff 2:请注意,遗憾的是 ComboBox 没有拾取其单元格的 BackColor。它仍然有助于设置它,因此您可以将其称为目标颜色。就像在下面的 darw 代码中一样,您将需要使用 e.Graphics.DrawXxx 调用和 TextRenderer.DrawText 的组合。为了更方便地引用它所属的 DGV 单元,您可能希望在 EditingControlShowing 事件中设置 CurrentCell 时将其存储在引用 ComboBoxTag 中。

drawstuff 3:所选项目可能具有特殊的字体和背景颜色

drawstuff 4:常规项目就是这样:相当常规..


下面的代码是我的答案的原始版本,只涵盖案例3&4:

下面是一个简短的示例,向您展示如何绘制DataGridViewComboBox。请注意,我只展示了最低限度,并没有画彩色方块..:

我们首先定义一个对单元格的类级引用:

ComboBox theBoxCell = null;

EditingControlShowing 中我们设置引用,添加事件处理程序并将其设置为所有者绘制模式:

private void dataGridView1_EditingControlShowing(object sender,
             DataGridViewEditingControlShowingEventArgs e)

    theBoxCell = (ComboBox) e.Control;
    theBoxCell.DrawItem += theBoxCell_DrawItem;
    theBoxCell.DrawMode = DrawMode.OwnerDrawVariable;

最后我们添加绘制代码:

void theBoxCell_DrawItem(object sender, DrawItemEventArgs e)

    if (e.Index < 0) return;
    string t = theBoxCell.Items[e.Index].ToString();
    using (SolidBrush brush = new SolidBrush(
        (e.State & DrawItemState.Selected) != DrawItemState.None ?
                   Color.LightCyan : Color.LightGray))
        e.Graphics.FillRectangle(brush, e.Bounds);
    e.DrawFocusRectangle();
    e.Graphics.DrawString(t, Font, Brushes.DarkGoldenrod, e.Bounds.X + 6, e.Bounds.Y + 1);


我们也可以将 linq 中的绘制代码添加到事件挂钩中......

结果如下:

【讨论】:

如果我的问题表述不当,我很抱歉。我已经可以画出你所展示的一切了。但是没有焦点的非活动 DataGridView 行呢? 与此同时,我想我已经明白了。我添加了答案。 好吧,这并没有回答问题,实际上要画什么。毕竟,用户应该会看到一个箭头,如果您希望它也被着色,那么您需要一些代码行,不是吗? 哈,这些事情发生在 cmets - 双方都不太了解对方的意思。稍后我将更新我的答案,以一种很好的方式包括 DGVComboBoxCells 的绘画,但 atm 我正坐在 inisde heatwave ;-) - 我将涉及 DGV 的 CellPainting 事件和箭头的 ComboBoxRenderer .. - 也是DrawItem 代码的扩展,以便在e.Index==-1 时正确绘制 我会对添加的建议感到满意,这也会为其他人创造价值。答案中提出的解决方案的最大缺点是该列绑定到DataGridView1.EditingControlShowing 事件。因此,您必须为每个 DataGridView 一次又一次地创建独特的 EditingControlShowing 方法 + DrawItem() 绘画。如果一个人像我一样有 50 多个网格,那不是很聪明。我认为更具创新性的方法是将自定义绘画绑定到 DGV 列的实例。你觉得可以help me with that?

以上是关于如何在 DataGridViewComboBox 列中绘制非活动行?的主要内容,如果未能解决你的问题,请参考以下文章

如何从数据库 vb.net 将项目添加到 datagridviewcombobox

在 DataGridViewComboBox 下拉列表中设置特定项目的颜色

datagridviewcombobox columns 依赖于另一列

DataGridViewCombobox 列中的自动完成有啥奇怪的行为?

值未显示在 DataGridViewComboBox 控件上

在 DataGridViewComboBox 列上设置值非常慢