Странная проблема с ListBox.DataSource - PullRequest
9 голосов
/ 24 марта 2009

Я пишу приложение для Windows и использую элемент управления Listbox. Я занимаюсь разработкой Visual Studio C # 2008 Express Edition.

У меня есть объект данных, который выглядит примерно так

public class RootObject
{
   public List<SubObject> MySubObjects{ get; set;}
}

В моей форме есть ListBox, а также свойство "MyRootObject", которое, очевидно, содержит RootObject. Когда элемент управления инициализирован, я установил:

_listBox.DataSource = MyRootObject.MySubObjects;

Теперь, когда форма загружается, я отлаживаю и вижу, что источник данных установлен правильно. Но ничего не отображается. Я переопределил метод ToString () SubObject, и он даже не вызывается. Я попытался установить _listBox.DisplayMember для свойства SubObject, просто чтобы посмотреть, есть ли там какая-то проблема, но все еще ничего. Я пытался вызвать _listBox.Update () и _listBox.Refresh () после установки DataSource, но все равно не любил. DataSource содержит все данные ... он просто отказывается отображать их.

Итак, во время отладки я удивился WTF и решил просто сделать

_listBox.DataSource = new List<SubObject>{ new SubObject(), new SubObject() };

Конечно, это сработало, и я вижу две вещи, перечисленные в моем списке.

Итак, очень любопытно, я решил попробовать скопировать список объектов и поместить его в список, например, так:

_listBox.DataSource = MyRootObject.MySubObjects.ToArray();

Это работает! И это временное решение моей проблемы ... но очень раздражающее. Кто-нибудь знает, почему мне нужно в основном копировать список объектов, подобных этому, чтобы заставить его работать, а не просто устанавливать _listBox.DataSource = MyRootObject.MySubObjects; ? Опять же, DataSource имеет все нужные данные в любом случае после их установки ... просто когда они копируют данные, они действительно отображаются, а когда нет, они не отображаются.

Ответы [ 8 ]

5 голосов
/ 20 мая 2009
((CurrencyManager)_listBox.BindingContext[_listBox.DataSource]).Refresh();

Sux0r Я знаю, но это работает. (первоначально найденный ответ здесь )

1 голос
/ 31 марта 2009

, насколько мне известно, всякий раз, когда вы хотите установить коллекцию в

[ComboBox,ListBox].DataSource

Вы должны установить DisplayMember и ValueMember. DisplayMember и ValueMember заполнены именем свойства класса в коллекции, которая назначена списку / комбинированному списку. Ex.

//Populate the data
RootObject root = new RootObject();
root.MySubObjects.Add(new SubObject("1", "data 1"));
root.MySubObjects.Add(new SubObject("2", "data 2"));

//Assign data to the data source
_listBox.DisplayMember = "DisplayProperty";
_listBox.ValueMember = "ValueProperty";
_listBox.DataSource = root.MySubObjects;

root.MySubObjects возвращает список SubObject, и SubObject должен иметь свойства, называемые DisplayProperty и ValueProperty, например.

public class RootObject
{
     public List<SubObject> MySubObjects { get; set; }
}

public class SubObject
{
     public string ValueProperty { get; set; }
     public string DisplayProperty { get; set; }
}
1 голос
/ 24 марта 2009

В общем, это потому, что свойство ListBox.DataSource должно содержать что-то, что реализует интерфейс IList. Ваш универсальный List<SubObject> не реализует IList; он реализует IList<T> (в пространстве имен System.Collections.Generic). Array объекты, с другой стороны, наследуются от IList, поэтому передача данных через этот тип объектов работает.

Вы можете попробовать вытянуть Enumerator (который также реализует IList) из вашего List<SubObject> объекта и подключить его. Если это работает, то проблема, которую я описал, это ваша проблема. Если это не так, то я говорю из своей шляпы.

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

0 голосов
/ 05 апреля 2009

У меня есть специальное правило для подобных проблем, которое я всегда стараюсь помнить, прежде чем тратить на это целый день (поверьте мне, я потратил много дней на это!) Правило таково: когда поведение системы действительно странное, причина должна быть очень глупой. Как интеллектуальные программисты, мы склонны искать эзотерические причины или ошибки в программном коде, чтобы объяснить наши проблемы. Иногда ответ таков: мы спешили и совершили неосторожную ошибку, которую еще не заметили.

По словам Шерлока Холмса, «когда вы удалили невозможное, тогда все, что остается, каким бы невероятным оно ни было, должно быть правдой». В этом случае невероятная истина заключается в том, что свойство MySubObjects объекта MyRoot имеет значение null.

0 голосов
/ 03 апреля 2009

Вы можете попробовать

_listBox.DataSource = new BindingList<SubObject> (MyRootObject.MySubObjects);

вместо этого. BindingList реализует несколько больше интерфейсов, чем List, которые необходимы для DataBinding.

0 голосов
/ 28 марта 2009

Полагаю, вам нужно вызвать _listbox.DataBind (); после назначения источника данных. Однако я никогда раньше не использовал свойство в качестве источника данных, я использовал только методы. Вы пытались изменить свое свойство на метод, чтобы увидеть, если это проблема?

0 голосов
/ 27 марта 2009

вы можете попробовать использовать BindingSource (http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx)

между списком и вашей коллекцией. Bindingsources обрабатывает множество вещей, а также включает свойства Suspend / ResumeBinding, которые могут быть полезны при обновлении списка

Вы также можете попробовать wpf, так как его привязка данных намного превосходит таковую для winforms :), но, возможно, это невозможно в вашем случае

0 голосов
/ 24 марта 2009

Я думаю, что вам нужно вызвать метод Bind после назначения источника данных в списке что-то вроде _listBox.DataSource.bind () и ваш список исчезнет

...