开发者

How to show Enum type members in a DataGridViewComboBox?

What else I have to do in order to show ReadAccess enum members in this DatagridViewComboBox?

ReadDataGridViewComboBoxColumn.Items.Clear();
ReadDataGridViewComboBoxColumn.Items.AddRange(ReadAccess.None, ReadAccess.Allowed);
ReadDataGridViewComboBoxColumn.ValueType = typeof(ReadAccess);

here is designer-generat开发者_运维问答ed codes about DataGridView:

this.rolesDataGridView.AutoGenerateColumns = false;
this.rolesDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.TableNameDataGridViewTextBoxColumn,
this.ReadDataGridViewComboBoxColumn,
this.WriteDataGridViewComboBoxColumn,
this.ReadCodeDataGridViewComboBoxColumn,
this.ProcessDataGridViewCheckBoxColumn,
this.AdministrateDataGridViewCheckBoxColumn});
this.rolesDataGridView.DataSource = this.bsTablePermissions;

and finally, in after InitializeComponent();, i'm setting DataGridView's DataSource:

this.rolesDataGridView.DataSource = this.RoleTablePermissions;  // a bindingsource list


This is a problem i've come across many times. The DataGridViewComboBoxColumn doesn't know how to reconcile the difference between the enum's string representation and its integral value. Even though you set ValueType to the type of the enum, the DataGridView will try to set the cell's value to the underlying int value - this is why a FormatException will be raised during databinding.

The only way i've found to overcome this problem (short of subclassing the cell type) is to bind the DataGridViewComboBoxColumn to a data source which separates the string values from the integer values. You can use an anonymous type for this purpose:

ReadDataGridViewComboBoxColumn.ValueType = typeof(ReadAccess);
ReadDataGridViewComboBoxColumn.ValueMember = "Value";
ReadDataGridViewComboBoxColumn.DisplayMember = "Display";
ReadDataGridViewComboBoxColumn.DataSource = new ReadAccess[]
    { ReadAccess.None, ReadAccess.Allowed }
    .Select(value => new { Display=value.ToString(), Value=(int)value })
    .ToList();

This way, the DataGridView knows how to relate the cell value with its formatted value.


Adding to the answer Bradly Smith provided: One can get all Enum values (instead of naming each individually) easily using this code:

    ReadDataGridViewComboBoxColumn.DataSource =
        new List<ReadAccess>((ReadAccess[]) Enum.GetValues(typeof(ReadAccess)))
        .Select(value => new { Display=value.ToString(), Value=(int)value })
        .ToList();


You should not convert enum value to the int. Use this code if you have an error like "invalid value":

ReadDataGridViewComboBoxColumn.DataSource = new ReadAccess[]
{ ReadAccess.None, ReadAccess.Allowed }
.Select(value => new { Display=value.ToString(), Value=value })
.ToList();


An Improvement to accepted answer: There is no need to type enum members as array manually. Instead you can use System.Enum.GetValues(typeof(ReadAccess)). Also, instead of anonymous type list, you can use a List from Dictionary (Dictionary isn't accepted as datasource):

ReadDataGridViewComboBoxColumn.DataSource= System.Enum.GetValues(typeof(ReadAccess))
  .Cast<Enum>.ToDictionary<string, Enum>((e) => e.ToString(), (e) =>  e).ToList;

or directly a KeyValuePair list :

ReadDataGridViewComboBoxColumn.DataSource = System.Enum.GetValues(typeof(ReadAccess))
  .Cast<Enum>.Select((value) => new KeyValuePair<string, enum>(value.ToString(), (value)));

Still necessary (but DisplayMember now is "Key") :

 ReadDataGridViewComboBoxColumn.ValueType = typeof(ReadAccess);
 ReadDataGridViewComboBoxColumn.ValueMember = "Value";
 ReadDataGridViewComboBoxColumn.DisplayMember = "Key";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜