ComboBox 已设置 DataSource 但未显示任何项目

Posted

技术标签:

【中文标题】ComboBox 已设置 DataSource 但未显示任何项目【英文标题】:ComboBox has DataSource set but is not displaying any items 【发布时间】:2021-11-09 20:21:43 【问题描述】:

我有一个带有ComboBox DisplayBox 的窗体。在我的 ViewModel 中,我现在有一个要绑定到 DisplayBox 的属性 BindingList<MyObject> ObjectBindingList

当我加载表单时,DisplayBox 不显示任何文本。

属性DataSource在数据下载后检入调试模式时设置并保存MyObjects的列表。 属性项的计数始终为零。

我的代码如下:

在启动时,我将表单类中的数据绑定设置为仍然为空的 List ObjectBindingList。

displayBox.DataSource = ObjectBindingList;

DisplayMemberValueMember 在 GUI 设计器的组合框属性中设置。controller 异步下载一些数据(MyDataObjects)异步。然后通过添加将ViewModel中的BindingList<MyObject> ObjectBindingList设置为下载的Objects。

【问题讨论】:

Debug。在上面显示的行上设置断点并检查集合ObjectBindingList。里面有物品吗?注意:如果您使用的是BindingSource 对象,则将绑定列表分配给绑定源的DataSource,而不是直接分配给组合框。 ObjectBindingListList<MyObject> 还是 BindingList<MyObject>?你提到了两者。 -- 在将项目添加到List(?) 后,您是否重置了绑定? @Jimi 是一个BindingList,绑定列表被清空然后用ObjectBindingList.Add(downloadData[i].MyObject)函数填充。 @OlivierJacot-Descombes 不,因为当我绑定数据时下载尚未发生,所以 ObjectBindingList 已设置但没有项目( items.count = 0)。我想在下载完成后设置实际数据并相应地更新 ComboBox。 如何添加数据? 【参考方案1】:

由于我没有看到所有相关代码,我只能假设发生了什么。

您可能看不到 ComboBox 中的数据,因为您在加载数据时正在创建一个新的 BindingList。但是 ComboBox 仍然附加到旧的空列表中。

您使用一个空列表初始化数据源,如下所示:

// Property
BindingList<MyObject> ObjectBindingList  get; set; 

别处

// Initializes data source with an empty `BindingList<MyObject>`.
ObjectBindingList = new BindingList<MyObject>();
displayBox.DataSource = ObjectBindingList;

稍后,您加载数据并替换列表:

ObjectBindingList  = LoadData();

现在,您有两个列表:分配给displayBox.DataSource 的初始空列表和分配给属性ObjectBindingList 的新填充列表。请注意,displayBox.DataSource 没有对属性本身的引用,因此它看不到该属性的新值。

要使BindingList&lt;T&gt; 按预期工作,您必须添加项目

var records = LoadData();
foreach (var data in records) 
    ObjectBindingList.Add(data);

即,保留分配给数据源的原始BindingList&lt;MyObject&gt;


另请参阅:How can I improve performance of an AddRange method on a custom BindingList?


为避免该问题,建议将属性设为只读(使用 C# 9.0 的 Target-typed new expressions)。

BindingList<MyObject> ObjectBindingList  get;  = new();

【讨论】:

【参考方案2】:

似乎在尝试从与主窗体线程不同的线程更新 ComboBox 时,更新没有到达控件。 我现在在 Binding List 和控件之间使用 Invoke 方法和 BindingSource 对象。

private void SetBindingSourceDataSource( BindingList<MyObject> myBindingList)

    if (InvokeRequired)
    
        Invoke(new Action<BindingList<MyObject>>(SetBindingSourceDataSource),  myBindingList);
    
    else 
        this.BindingSource.DataSource = myBindingList;
    

我特别在 PropertyChanged 事件上调用上述函数,该事件在每次调用下载函数结束时触发。

【讨论】:

以上是关于ComboBox 已设置 DataSource 但未显示任何项目的主要内容,如果未能解决你的问题,请参考以下文章

在没有DataSource的ComboBox上设置DisplayMember和ValueMember

DataSource 更改时,ComboBox 不会自动更新?

绑定到 DataSource 的 ComboBox 需要添加默认值(空白或在此处添加)和设置回退的能力

当 DataSource 值更改时,WinForms ComboBox 中的项目不会更新

WinForm 中ComboBox 绑定总结

comboBox的id返回System.Data.DataRowView