Вопрос

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

var data = (from item in someTable
            select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance

Я что-то упускаю?возможно ли привязать данные к сложному объекту?

Обновить:

Я реализовал TypeConverter и переопределил CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom .Теперь я начинаю понимать

Исключение FormatException:Значение DataGridViewComboBoxCell недопустимо

Есть какие-нибудь идеи?

Это было полезно?

Решение

Вы упускаете возможную деталь.

column.DataPropertyName = "Foo";
column.DisplayMember = "SomeNameField"; 
column.ValueMember = "Bar"; // must do this, empty string causes it to be 
                            // of type string, basically the display value
                            // probably a bug in .NET
column.DataSource = from foo in Foo select foo;
grid.DataSource = data;

Обновить:

На самом деле, после повторного прочтения вашего вопроса, я думаю, вы столкнулись с отмеченной ошибкой.К сожалению, нет способа заставить его возвращать связанный объект без использования пользовательского TypeDescriptor / TypeConverter / BindingSource.

Ответ для привязки к сложному объекту.По умолчанию - нет.Я написал довольно хорошую статью для моего текущего проекта.Это включает в себя создание пользовательского TypeDescriptor / TypeConverter / BindingSource, который возвращает все вложенные свойства.Еще одна "ошибка", вы не можете использовать "." вместо разделителя элементов мне пришлось прибегнуть к ":".

Другие советы

столбец DataGridViewComboBoxColumn всегда должен содержать все возможные значения в списке элементов combobox, иначе он вызовет "FormatException:Значение DataGridViewComboBoxCell недопустимо".

Если вы пытаетесь вернуть значения, выбранные из одного столбца со списком, вы можете обработать событие DataGridView CellParsing и получить выбранный элемент из DataGridView.EditingControl, потому что он будет установлен для управления редактированием из редактируемого столбца.Вот пример:

private void dataGridView1_CellParsing(object sender, 
 DataGridViewCellParsingEventArgs e) {
   if (dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn) {
       DataGridViewComboBoxEditingControl editingControl = 
                (DataGridViewComboBoxEditingControl)dataGridView1.EditingControl;
       e.Value = editingControl.SelectedItem;
       e.ParsingApplied = true;
   }
}

Вы также можете настроить способ отображения ваших объектов в каждой ячейке, обработав событие форматирования ячейки, вот код, который отображает toString для любого объекта или интерфейса.

private void dataGridView1_CellFormatting(object sender, 
    DataGridViewCellFormattingEventArgs e) {
        if (e.Value != null) {
            e.Value = e.Value.ToString();
            e.FormattingApplied = true;
        }
    } 

Обрабатывает эти два события должно быть достаточно для отображения и редактирования данных внутри любого бизнес-объекта и его упрощения, после чего записывает преобразователи типов.Для этой работы установите DataGridView и столбец combobox следующим образом:

var data = (from item in someTable
        select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList ();

Не нужно устанавливать свойство DisplayMember или ValueMember , просто убедитесь, что в вашем списке источников данных combobox есть все возможные значения для Foo .

Надеюсь, это поможет.

На самом деле, вы можете использовать сложный тип в DataGridViewComboBoxColumn.

Например:

DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);

Self является:

public ValueModeItem Self
{
    get
    {
        return this;
    }
}

Очень важно - необходимо переопределить метод 'Equals' сложного типа.В моем случае:

public override bool Equals(object obj)
{
    if (obj is ValueModeItem && obj != null)
    {
        if (...)
            return true;
    }
    return false;
}

Я постоянно сталкивался с одной и той же проблемой, пока не обнаружил, что вы не можете установить DisplayMember из числа DataGridViewComboBoxCell без установки ValueMember слишком.
Таким же образом, устанавливая ValueMember и не тот DisplayMember это тоже сбой, вы должны определить none или оба варианта.

Ваша модель Foo, и вы, конечно же, хотите, чтобы значением ComboBox был сам элемент.Для этого самый простой способ - это тоже создать свойство в вашем foo, возвращающее само себя.

public class Foo
{
    ...
    public Foo This { get {return this; } }
}

Тогда привязки становятся:

column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
column.ValueMember = "This";

Это должно сработать, и Значение ячейки должно быть типа Foo, как и ожидалось.

Интересная ссылка: Проблемы со столбцом DataGridViewComboBoxColumn

Однако DataGridViewComboBoxColumn работает не так, хотя он будет отображать значение toString, если вы не установите DisplayMember, что-то внутри идет не так, когда он пытается просмотреть при запуске SelectedItem вы должны присвоить DisplayMember значение public свойству вашего класса.Хуже того, поведение по умолчанию, если вы этого не сделаете установите свойство ValueMember для возврата DisplayMember, нет способа получить сам фактический элемент.Единственный способ обойти это добавить свойство к вашему классу, которое возвращает само себя, и присвоить этому свойству значение ValueMember.Конечно, если ваш элемент не является чем-то, что вы можете изменить (например, один из классов framework), вам придется объединить объект контейнера, который содержит ссылку на ваш элемент.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top