Установка DataRow в качестве значения элемента ComboBox - PullRequest
1 голос
/ 04 мая 2009

Я заполняю элементы в моем ComboBox из файла XML, используя DataTable. В настоящее время он настроен так, что один столбец является отображаемым элементом ComboBox, а другой - его значением. Однако это может не всегда работать для меня, так как я должен установить параметр selectedItem, и значение member может не быть уникальным.

Я не знаю, есть ли дубликат значения элемента в таблице или нет, поэтому я подумал, что я бы поместил весь DataRow в качестве значения элемента ComboBox, а затем использовать ComboBox.SelectedITem = (DataRow) some_data_row; для выбора, и он всегда будет выбирать правильный объект ComboBox.

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

Спасибо за помощь!

РЕДАКТИРОВАТЬ : Возможно, я не был достаточно ясен раньше, однако, хотя я спрашиваю, является ли это лучшим подходом здесь, я также спрашиваю , как сделать это. Если я не установил параметр valuemember, SelectedItem имеет тип DataRowView ... Обратите внимание, что я хочу использовать параметр selectedValue для выбора элементов в ComboBox, и если я пытаюсь сделать это без явной установки элемента значения исключение.

Ответы [ 3 ]

1 голос
/ 04 мая 2009

Если вы связываете ListBox с DataTable, вы фактически привязываете его к DataView, который представляет DataTable (DataTable реализует IListSource и возвращает DataView) , Вы не можете напрямую установить SelectedItem на DataRow экземпляр, вы должны установить его на DataRowView экземпляр. К сожалению, нет простого способа получить DataRowView из DataRow.

Вы бы лучше просто делали все свои взаимодействия через DataRowView. Это позволит вам установить SelectedItem явно.

Вы не можете использовать свойство SelectedValue, для этого вы должны использовать SelectedItem.

0 голосов
/ 20 февраля 2015

Это самый простой способ получить DataTable в комбинированный список

private void load() { 
DataTable dt = // get data from DB 
comboBox1.ValueMember = null; // allows you to get all fields in the obj to combobox
comboBox1.DisplayMember = "ccType";//label displayed from dt
comboBox1.DataSource = dt;
}
//to test 
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {

        DataRowView current = (DataRowView)comboBox1.SelectedValue;
        string drs = current.Row["ID"].ToString();

    }
0 голосов
/ 04 мая 2009

Прежде всего, спасибо, Адам Робинсон, я уверен, что ваш ответ был правильным, но я просто не хотел этого слышать. Я решил свою проблему по-другому, и я думаю, что она может быть полезна кому-то еще, поэтому я публикую ее здесь.

То, что я сделал, я создал новый класс, в моем случае я назвал его ListObject, у которого было свойство DataRow (как вы увидите позже, оно работает и для других типов, я просто использовал это, так как это то, что я на самом деле хотел как мое свойство значения элемента). Также переопределяет методы:

  • String ToString ()
  • bool Equals (объектный объект)
  • int GetHashCode () - в моем случае не требуется, однако Visual Studio
    предупреждает вас, что это должно быть отменено.

Идея заключалась в том, что я мог бы заполнить коллекции ComboBox.Items объектами своего собственного класса, отобразить пользовательскую строку (если бы я не работал так, мой следующий вопрос о переполнении стека, вероятно, был бы о настройке DisplayMembers при чтении элементы из DataRow) и сравнить только один элемент класса (в моем случае DataRow).

Итак, вот код, и он прекрасно работает (по крайней мере, для того, что я хотел с ним сделать).

public class ListObject
{
    public DataRow element;

    public String DisplayObject = null;

    public ListObject(DataRow dr)
    {
        element = dr;
    }

    public ListObject(DataRow dr, String dspObject)
    {
        element = dr;
        DisplayObject = dspObject;
    }

    public override String ToString()
    {
        if (DisplayObject == null) throw new Exception("DisplayObject property was not set.");

        return element[DisplayObject].ToString();
    }

    public override bool Equals(object obj)
    {
        if (obj.GetType() == typeof(ListObject))
            return Equals(((ListObject)obj).element, this.element);
        else return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

В моем случае это прекрасно работает, так как я могу просто заполнить ComboBox оператором foreach:

dtUsers.ReadXml(Program.Settings.xmlInputUsers);

foreach(DataRow dr in dtUsers.Rows) 
{
    cmbUser.Items.Add(new ListObject(dr, "Name"));
}

И когда я получаю DataRow, который я хочу выбрать, я просто делаю это:

cmbUser.SelectedItem = new ListObject(dlg.SelectedDataRow);

Где мне не нужно беспокоиться о DisplayMember и т. Д., Потому что будут сравниваться только DataRow, и ваши параметры отображения будут по-прежнему устанавливаться с момента заполнения коллекции ComboBox.Items. Кроме того, поскольку метод toString переопределен, вы действительно можете настроить свой вывод.

Создание этого класса стало возможным только из-за статьи msdn Свойство ComboBox.SelectedItem , в котором было отмечено, что свойство SelectedItem работает с использованием метода IndexOf. Этот метод использует метод Equals для определения равенства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...