2

I have a DataTable which contains columns of various data types - int, string, bool, Enum( like Severity in below example):

hostTable = new DataTable();
hostTable.Columns.Add("Suspended", typeof(bool));
hostTable.Columns.Add("Succ Tests", typeof(int));
hostTable.Columns.Add("Unsucc Tests", typeof(int));
hostTable.Columns.Add("System Name", typeof(string));
hostTable.Columns.Add("System IP", typeof(string));
hostTable.Columns.Add("Criticality", typeof(Severity));
hostTable.Columns.Add("Alert Email To", typeof(string));
hostTable.Columns.Add("Alert Email Cc", typeof(string));
hostTable.Columns.Add("Likely Impact", typeof(string));
hostTable.Columns.Add("Likely Causes", typeof(string));
hostTable.Columns.Add("Escalation", typeof(string));

hostTable.Rows.Add((bool)hd.IsSuspended, (int)hd.SuccTests, (int)hd.UnSuccTests,
    hd.SystemName, hd.SystemIp, (Severity)hd.Criticality, hd.AlertEmailToAddress, 
    hd.AlertEmailCcAddress, hd.LikelyImpact, hd.LikelyCauses, hd.EscalationInstructions);

dgvHostTable.DataSource = hostTable;

When I bind this to a DataGridView, how can I make the columns show with this settings:

  • bool columns → ComboBox with true/false options
  • Enum columns → ComboBox with the list of enums
  • String columns → Just as editable text field
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Quantum_Kernel
  • 303
  • 1
  • 7
  • 19

1 Answers1

4

You should add DataGridViewComboBox column for those columns yourself. You can create a reusable method to do it for you.

In below code, I checked all columns of the DataGridView control and for each column, if it was bound to a bool property or an Enum property, I used a DataGridViewComboBoxColumn instead:

public void UseComboBoxForEnumsAndBools(DataGridView g)
{
    g.Columns.Cast<DataGridViewColumn>()
     .Where(x => x.ValueType == typeof(bool) || x.ValueType.IsEnum)
     .ToList().ForEach(x =>
     {
         var index = x.Index;
         g.Columns.RemoveAt(index);
         var c = new DataGridViewComboBoxColumn();
         c.ValueType = x.ValueType;
         c.ValueMember = "Value";
         c.DisplayMember = "Name";
         c.DataPropertyName = x.DataPropertyName;
         c.HeaderText = x.HeaderText;
         c.Name = x.Name;
         if (x.ValueType == typeof(bool))
         {
             c.DataSource = new List<bool>() { true, false }.Select(b => new
             {
                 Value = b,
                 Name = b ? "True" : "False" /*or simply b.ToString() or any logic*/
             }).ToList();
         }
         else if (x.ValueType.IsEnum)
         {
             c.DataSource = Enum.GetValues(x.ValueType).Cast<object>().Select(v => new
             {
                 Value = (int)v,
                 Name = Enum.GetName(x.ValueType, v) /* or any other logic to get text */
             }).ToList();
         }

         g.Columns.Insert(index, c);
     });
}

Example

You can simply test the solution using below code:

public enum MyEnum { First, Second, Third }
private void Form1_Load(object sender, EventArgs e)
{
    var dt = new DataTable();
    dt.Columns.Add("C1", typeof(bool));
    dt.Columns.Add("C2", typeof(MyEnum));
    dt.Columns.Add("C3", typeof(string));
    dt.Rows.Add(true, MyEnum.First, "string");
    this.dataGridView1.DataSource = dt;
    UseComboBoxForEnumsAndBools(this.dataGridView1);
}

enter image description here

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398