Нестроковые значения в DataGridViewComboBoxColumn, вызывающие DataErrors в DataGridView - PullRequest
4 голосов
/ 03 января 2012

У меня есть программно заполненный DataGridView с некоторыми DataGridViewComboBoxColumn записями.Эти ComboBox содержат пользовательские типы, у которых ToString() перезаписаны, чтобы скрыть свои внутренние кишки от пользователя.

Проблема: всякий раз, когда я изменяю значение ComboBox и выбираю другую ячейку, вызывается CellValidating,FormattedValue - это строковый результат моего пользовательского FooBar.ToString () (должно быть в порядке).В CellEndEdit ValueType внезапно становится строкой, а не моим пользовательским типом, и я получаю сообщение об ошибке либо при просмотре row.Cell-Member в VS, либо при наведении курсора на измененную ячейку (перевод с немецкого):

"DataGridView-Exception: System.ArgumentException: DataGridViewComboBoxCell -Value недопустимо. Обработайте DataError-Exception, чтобы заменить это диалоговое окно"

Вот как создается столбец - colFoo DataGridViewComboBoxColumn:

    dataGridInstance.Columns[1].CellTemplate.Value = new FooBar("bla", 31);
    dataGridInstance.Columns[1].CellTemplate.ValueType = typeof(FooBar);

    foreach (FooBar foo in FooBarArray)
            colSymbol.Items.Add(sym);

Сетка заполняется так:

    foreach (FooLine line in SomeFooLineArray)
    { 
        DataGridViewRow newRow = ((DataGridViewRow)dataGridInstance.RowTemplate.Clone());
        newRow.Cells[1].Value = line.Foo; // FooBar instance field
        dataGridInstance.Rows.Add(newRow);
    }

Любые эксперименты в CellValidating или CellFormatting провалились, я всегда получаю это сообщение.

Как я могу добавить пользовательские типы в существующий DataGridView без перезаписи?Почти каждый другой Компонент (включая выпадающие списки) просто отлично поддерживает пользовательские типы, проблема заключается только в копировании значения из Combo в швы сетки.

Как уже было сказано, реализация FooBar выглядит следующим образом:

 internal class FooBar {
        private readonly int id;
        private readonly string name;
        internal FooBar(string n, int i) 
        { 
              id = i; name = n;
        }
        public override string ToString() 
        {
              return name;
        }
 }

Это делает немного больше, но это инкапсулированная значимая функциональность.

Ответы [ 3 ]

0 голосов
/ 06 марта 2017

Я знаю, что это старый вопрос, но я только что столкнулся с этой проблемой, и я надеюсь, что решение полезно.

Во-первых, DataGridViewComboBoxColumn прекрасно работает, если вы используете строки. Идея иметь ComboBox с использованием объектов великолепна (и именно то, что я хотел), но если это то, что вы хотите, то есть несколько препятствий, которые вам нужно преодолеть (возможно, потому что разработчики забыли).

Первый - установить ValueType столбца (который вы делаете в своем коде), т.е.:

dataGridInstance.Columns[1].CellTemplate.ValueType = typeof(FooBar);

или вы можете установить его прямо в столбце:

dataGridInstance.Columns[1].ValueType = typeof(FooBar);

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

private void dataGridInstance_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
    if (e.DesiredType == typeof(ListItem))
    {
        if (e.Value != null)
        {
            DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridInstance.Rows[e.RowIndex].Cells[e.ColumnIndex];
            foreach (object item in comboCell.Items)
            {
                if (item.ToString() == e.Value.ToString())
                {
                    e.Value = item;
                    e.ParsingApplied = true;
                    return;
                }
            }
        }
    }
}

Вот и все.

Один вопрос: да, если два объекта имеют одно и то же представление .ToString(), это не расскажет об этом отдельно (но это ограничение присуще элементу управления). Поэтому, если вы можете убедиться, что строковое представление уникально.

0 голосов
/ 03 июля 2019

Ваши столбцы должны иметь одинаковый тип данных

Let Say

TableForComboColumn id Int32 имя Varchar

TableWithComboColumn

id Int32 TableForComboColumn_id Int16 -> также должно быть Int32

0 голосов
/ 04 января 2012

пытались ли вы изменить

internal FooBar(string n, int i)
{
   id = i; name = n;
} 

to read like this 

internal FooBar(string n, int i)
{
   this.id = i; this.name = n;
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...