Как показать элементы типа Enum в DataGridViewComboBox? - PullRequest
11 голосов
/ 08 ноября 2010

Что еще мне нужно сделать, чтобы показать ReadAccess перечисление членов в этом DatagridViewComboBox?

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

вот сгенерированные дизайнером коды о 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;

и, наконец, после InitializeComponent(); я устанавливаю DataSridView DataGridView:

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

Ответы [ 4 ]

21 голосов
/ 08 ноября 2010

Это проблема, с которой я сталкивался много раз. DataGridViewComboBoxColumn не знает, как согласовать разницу между строковым представлением перечисления и его интегральным значением. Даже если вы установите ValueType в качестве типа перечисления, DataGridView попытается установить значение ячейки в базовое значение int - вот почему FormatException будет повышаться во время привязки данных.

Единственный способ, который я нашел, чтобы преодолеть эту проблему (если не считать подклассы типа ячейки), - это связать DataGridViewComboBoxColumn с источником данных, который отделяет строковые значения от целочисленных значений. Для этой цели вы можете использовать анонимный тип:

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();

Таким образом, DataGridView знает, как связать значение ячейки с его отформатированным значением.

8 голосов
/ 08 июля 2011

Добавление к ответу, предоставленное Брэдли Смитом: можно легко получить все значения Enum (вместо именования каждого по отдельности), используя этот код:

    ReadDataGridViewComboBoxColumn.DataSource =
        new List<ReadAccess>((ReadAccess[]) Enum.GetValues(typeof(ReadAccess)))
        .Select(value => new { Display=value.ToString(), Value=(int)value })
        .ToList();
2 голосов
/ 25 апреля 2014

Вы не должны конвертировать enum-значение в int.Используйте этот код, если у вас есть ошибка типа «неверное значение»:

ReadDataGridViewComboBoxColumn.DataSource = new ReadAccess[]
{ ReadAccess.None, ReadAccess.Allowed }
.Select(value => new { Display=value.ToString(), Value=value })
.ToList();
0 голосов
/ 04 сентября 2017

Улучшение принятого ответа: Нет необходимости вводить члены перечисления в виде массива вручную. Вместо этого вы можете использовать System.Enum.GetValues(typeof(ReadAccess)). Кроме того, вместо списка анонимных типов вы можете использовать Список из словаря (словарь не является источником данных):

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

или непосредственно список KeyValuePair :

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

По-прежнему необходимо (но DisplayMember теперь является " Key "):

 ReadDataGridViewComboBoxColumn.ValueType = typeof(ReadAccess);
 ReadDataGridViewComboBoxColumn.ValueMember = "Value";
 ReadDataGridViewComboBoxColumn.DisplayMember = "Key";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...