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

How to paint inactive rows in DataGridViewComboBox column?

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

我看过、研究过并尝试过很多 classical ComboBox, but I don't understand all aspects of DataGridViewComboBox 的例子。

目前我有 DataGridViewCustomPaintComboBox class 来自 DataGridViewComboBox。提供的最小覆盖集是多少?你能给我指出正确的方向吗?

更新:

自定义绘图 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 没有选取其单元格的背景颜色。它仍然有助于设置它,因此您可以将其作为目标颜色。就像在下面的 darw 代码中一样,您将希望结合使用 e.Graphics.DrawXxx 调用和 TextRenderer.DrawText。为了更容易引用它所属的 DGV 单元格,您可能希望在 EditingControlShowing 事件中设置它时将 CurrentCell 存储在引用 ComboBoxTag 中。

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

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


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

这里是一个简短的例子,向您展示如何绘制 DataGridViewComboBox。请注意,我只展示了最低限度,并没有去画彩色方块..:[=​​35=]

我们首先定义对单元格的 class 级别引用:

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 中的绘制代码添加到事件连接中..

结果如下:

在没有焦点的情况下绘制非活动单元格所需的最小值似乎是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

    }

}