ListBox.DataSource的奇怪问题

时间:2009-03-23 22:44:48

标签: forms c#-3.0 listbox datasource

我正在编写Windows应用程序并使用Listbox控件。我正在使用Visual Studio C#2008 Express Edition进行开发。

我有一个看起来像这样的数据对象

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

我的表单上有一个ListBox,还有一个属性“MyRootObject”,它显然拥有一个RootObject。初始化控件时,我设置:

_listBox.DataSource = MyRootObject.MySubObjects;

现在,当表单加载时,我调试并看到正确设置了DataSource。但没有显示任何内容。我已经覆盖了SubObject的ToString()方法,甚至没有被调用。我尝试将_listBox.DisplayMember设置为SubObject的属性,只是为了查看是否存在某些问题,但仍然没有。我在设置DataSource后尝试调用_listBox.Update()和_listBox.Refresh(),但仍然没有爱。 DataSource拥有所有数据......它只是拒绝显示它。

因此,在调试时,我想知道WTF,我决定只做

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

果然,这很有效,我看到列表框中列出了两件事。

那么,真的很好奇,我决定尝试复制对象列表并将其放入列表框中,如下所示:

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

这个有效!现在这是解决我的问题的方法......但是非常讨厌。有谁知道为什么我需要基本上复制像这样的对象列表才能使它工作,而不是只设置_listBox.DataSource = MyRootObject.MySubObjects; ?同样,DataSource在设置之后以任何一种方式拥有所有正确的数据...它只是在复制数据时,它实际显示,而当它不复制时,它不会显示。

8 个答案:

答案 0 :(得分:5)

((CurrencyManager)_listBox.BindingContext[_listBox.DataSource]).Refresh();

Sux0r我知道,但这很有效。 (最初找到答案here

答案 1 :(得分:1)

在我的脑海中,这是因为ListBox.DataSource属性必须包含实现IList接口的内容。您的通用List<SubObject>未实现IList;它实现IList<T>(在System.Collections.Generic命名空间中)。另一方面,Array个对象继承自IList,因此通过这种对象传递数据是有效的。

您可以尝试从Enumerator对象中提取IList(也会实现List<SubObject>)并将其插入。如果有效,那么我所描述的问题就是您的问题问题。如果没有,那我就是在说话了。

如果这确实是问题,我很惊讶在一个不受支持的对象中推迟不会引发异常。

答案 2 :(得分:1)

到目前为止我知道,无论何时你想要将集合设置为

[ComboBox,ListBox].DataSource

您必须设置DisplayMember和ValueMember。 DisplayMember和ValueMember填充了分配给listbox / combobox的集合中Class的属性名称。实施例

//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的List,而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; }
}

答案 3 :(得分:0)

我认为你必须在分配到列表框数据源后调用Bind方法  像_listBox.DataSource.bind()之类的东西 并且你的列表框会消失

答案 4 :(得分:0)

您可以尝试使用BindingSource (http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx

在列表框和您的集合之间。 Bindingsources处理一堆东西,还包括Suspend / ResumeBinding属性,这些属性在更新列表时很有用

你也可以尝试使用wpf,因为它的数据绑定远远优于winforms :)但也许这在你的情况下是不可能的

答案 5 :(得分:0)

我相信你需要调用_listbox.DataBind();在分配数据源之后。 但是,我之前从未使用过属性作为数据源,我只使用了方法。您是否尝试将属性更改为方法以查看是否存在问题?

答案 6 :(得分:0)

你可以尝试

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

代替。 BindingList实现了比List更多的接口,这对于DataBinding来说是必不可少的。

答案 7 :(得分:0)

我对这样的问题有一个特殊的规则,我总是试着记住,然后浪费了整整一天的时间(相信我,我已经花了很多天锤击!)。规则是:当系统行为真的很奇怪时,根本原因必须是非常愚蠢的。作为智能程序员,我们倾向于在框架代码中搜索深奥的原因或错误来解释我们的问题。有时答案是我们匆忙并且犯了一个我们还没有抓到的粗心错误。

引用夏洛克·福尔摩斯的话说,“当你删除了不可能的东西时,无论剩下什么,无论多么不可能,都必须是真理”。在这种情况下,不可能的事实是MyRoot对象的MySubObjects属性为null。