2

I have code similar to this in a method that (re)creates the columns in the DataGridView:

MyColumn = new DataGridViewComboBoxColumn()
{
    Name = "..",
    HeaderText = "..",
    SortMode = DataGridViewColumnSortMode.NotSortable
};       
MyColumn.Items.Clear();
foreach (string s in MyStringList)
{
    MyColumn.Items.Add(s);
}
MyColumn.Items.Add(""); 
// I would like this empty string to be shown as "No group" 
// with an italic grayed out font

I think that I probably must create a class for the items of the ComboBox-es in the column, in which I should override the ToString() method, but I want to know how to format the No Group item.

A related question is here which is a about a normal ComboBox not inside a DataGridView, with the answer solving the problem using the DrawMode prperty and DrawItem event of the ComboBox class.

Community
  • 1
  • 1
silviubogan
  • 3,343
  • 3
  • 31
  • 57
  • Why not `MyColumn.Items.Add("No Group");` ? – Chetan Jan 01 '19 at 12:51
  • Thank you for your comment. I updated the question with "No Group" as the text that I want to format. – silviubogan Jan 01 '19 at 13:00
  • `MyColumn.DisplayStyle` is `DropDownButton` so you should be able to use `ComboBoxRenderer` class for `DrawDropDownButton` as explained here https://stackoverflow.com/a/7486187/2516718 – derloopkat Jan 01 '19 at 14:26
  • @derloopkat Thank you. This solves my problem partially, but I am looking for a way to paint the drop-down menus of the ComboBox-es inside a ComboBox column, besides the painting of the closed ComboBox-es. – silviubogan Jan 01 '19 at 15:02

1 Answers1

0

For custom-painting the ComboBox, you need to handle EditingControlShowing and then get the EditingControl which is DataGridViewComboBoxEditingControl and then set its DrawMode to OwnerDrawFixed and handle its DrawItem event.

For custom-painting the cell, you need to handle CellPainting event and set different font and color for the cell styles and let the paint continue with new values. You can also paint the whole cell if you want.

enter image description here

Example

Load Sample Data:

private DataTable LoadProducts()
{
    var dt = new DataTable();
    dt.Columns.Add("Name");
    dt.Columns.Add("CategoryId", typeof(int));
    dt.Rows.Add("P1", 1);
    dt.Rows.Add("P2", 1);
    dt.Rows.Add("P3", DBNull.Value);
    return dt;
}
private DataTable LoadCategories()
{
    var dt = new DataTable();
    dt.Columns.Add("Id", typeof(int));
    dt.Columns.Add("Name");
    dt.Rows.Add(DBNull.Value, "No Category");
    dt.Rows.Add(1, "C1");
    dt.Rows.Add(2, "C2");
    dt.Rows.Add(2, "C3");
    return dt;
}

Setup DataGridView Columnms:

private void Form1_Load(object sender, EventArgs e)
{
    var products = LoadProducts();
    var categories = LoadCategories();

    dataGridView1.Columns.Add(new DataGridViewTextBoxColumn()
    {
        Name = "NameColumn",
        DataPropertyName = "Name",
        HeaderText = "Name"
    });
    dataGridView1.Columns.Add(new DataGridViewComboBoxColumn()
    {
        Name = "CategoryIdColumn",
        DataPropertyName = "CategoryId",
        HeaderText = "Category",
        DataSource = categories,
        ValueMember = "Id",
        DisplayMember = "Name",
        DisplayStyle= DataGridViewComboBoxDisplayStyle.Nothing
    });
    dataGridView1.DataSource = products;
    dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
    dataGridView1.CellPainting += DataGridView1_CellPainting;
}

Handle EditingControlShowing

private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (dataGridView1?.CurrentCell?.OwningColumn?.Name != "CategoryIdColumn")
        return;
    var combo = e.Control as DataGridViewComboBoxEditingControl;
    if (combo == null)
        return;

    combo.DrawMode = DrawMode.OwnerDrawFixed;
    combo.DrawItem += (obj, args) =>
    {
        var txt = args.Index >= 0 ? combo.GetItemText(combo.Items[args.Index]) : "";
        var textColor = args.Index == 0 ? SystemColors.GrayText : SystemColors.ControlText;
        var font = args.Index == 0 ? new Font(combo.Font, FontStyle.Italic) : combo.Font;
        if ((args.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
            textColor = SystemColors.HighlightText;
        }
        args.DrawBackground();
        TextRenderer.DrawText(args.Graphics, txt, font,
            args.Bounds, textColor,
            TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
    };
}

Handle CellPainting

private void DataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex < 0 || e.RowIndex < 0 ||
            dataGridView1.Columns[e.ColumnIndex].Name != "CategoryIdColumn")
        return;
    if (dataGridView1[e.ColumnIndex, e.RowIndex].Value == DBNull.Value)
    {
        e.CellStyle.Font = new Font(e.CellStyle.Font, FontStyle.Italic);
        e.CellStyle.ForeColor = SystemColors.GrayText;
    }
    else
    {
        e.CellStyle.Font = new Font(e.CellStyle.Font, FontStyle.Regular);
        e.CellStyle.ForeColor = SystemColors.ControlText;
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398