绑定数据更改时Winforms列表框不更新
Posted
技术标签:
【中文标题】绑定数据更改时Winforms列表框不更新【英文标题】:Winforms listbox not updating when bound data changes 【发布时间】:2010-10-20 14:00:48 【问题描述】:下图显示了我的代码是如何工作的。当我按下按钮 2 时,列表框会更新,但当我按下按钮 1 时不会。为什么?
问题与线程有关吗?如果是,我应该在哪里添加对 (Begin)Invoke 的调用?
需要注意的一个有趣的事情是,如果我先按 button1,然后按 button2,那么当我点击 button2 时,会显示 button1 点击生成的数据。所以看起来 doFoo 生成的数据在某处缓冲,然后在我按下 button2 后推送到列表框。
编辑:
我尝试将 AddNumber 添加到表单代码中,并在 listBox1.InvokeRequired 返回 true 时添加对 Invoke 的调用。这解决了问题,但不是最好的设计。我不希望 GUI 不得不“担心”如何将项目添加到作为模型一部分的列表中。
如何保持添加到列表类内部列表背后的逻辑,同时在列表更改时仍更新 gui?
编辑 2:
既然我们已经确认这是一个线程问题,我已经更新了图像以更准确地反映我正在处理的实际代码的设计。
虽然 Lucero 的建议仍然可以解决问题,但我希望得到一些不需要表单来了解有关 dll 或 CDllWrapper 的任何内容。
模型(ListBoxDataBindingSource 等)应该对视图(列表框、按钮、标签等)一无所知
【问题讨论】:
【参考方案1】:我知道这是旧的,虽然我有一个非常相似的问题。
这是解决方案:BindingList not updating bound ListBox。
【讨论】:
谢谢。我很久以前就把这个项目搁置了,但是当我再次拿起它时,我会看看这是否有帮助:)【参考方案2】:我需要调用我的视图模型向绑定列表添加东西,所以我需要编写一个匿名函数
参考 Lucero 的回答和以下帖子: Anonymous method in Invoke call
我的代码:
listBox.Invoke((Action)delegate
MyViewModel.AddItem(param1, param2);
);
【讨论】:
【参考方案3】:我的猜测是这是因为更新消息在错误的线程上处理。背景:每个线程都有自己的消息队列。默认情况下,发布到消息队列中的消息将与调用者位于同一线程中。因此,回调可能会在错误的线程上发布消息。
试试这个:将 AddNumber() 方法移动到表单并使用 Invoke()(由 Control 继承)将项目添加到正确的线程中。这可能会解决问题。
编辑以反映您的后续行动: UI 不必知道您的组件。您需要的只是将项目添加到列表和 UI 之间的适当同步,因为 UI 更新仅在线程匹配时才起作用。因此,您可能希望将 Control 提供给包装 BindingList 的类,然后对列表本身执行 Invoke。这使得列表担心触发 UI 线程上的更新,并且确实消除了 UI 和外部组件在正确线程上调用处理程序的担心。
像这样:
internal class ListBoxDataBindingSource
private readonly Control uiInvokeControl;
private readonly BindingList<Item> list = new BindingList<Item>();
public ListBoxDataBindingSource(Control uiInvokeControl)
if (uiInvokeControl == null)
throw new ArgumentNullException("uiInvokeControl");
this.uiInvokeControl = uiInvokeControl;
CDIIWrapper.setFP(AddNumber);
public void AddNumber(int num)
Item item = new Item(num.ToString());
if (uiInvokeControl.InvokeRequired)
uiInvokeControl.Invoke(list.Add, item);
else
list.Add(item);
private BindingList<Item> List
get
return list;
【讨论】:
我明白问题出在哪里,现在我们只需要想出一个好的解决方案 :) 我正在尝试根据 MVC 模式进行设计,所以让 ListBoxDataBindingSource(模型的一部分)了解控件(视图的一部分)通常被视为不好的做法。 好吧,它并不真正了解控件,而只需要知道 hot 即可将 add 调用编组到正确的线程。您可以创建自己的编组类,该类知道控件并将其传递给列表,以便正确隐藏此方面。 (@Tobbe: 也许this answer 我之前的问题之一——Winforms data-binding to business objects in a multi-threaded scenario without InvokeRequired?——在这里适用。)【参考方案4】:不要让 setFP 将回调设置为 lbDataBindingSource.AddNumber,而是在代码中创建一个私有方法来处理回调,然后从该回调中调用 lbDataBindingSource.AddNumber。
void MyForm_Load(object sender, EventArgs e)
//...
cdll.setFP(FPCallback);
private void FPCallback(int num)
lbDataBindingSoruce.AddNumber(num);
【讨论】:
以上是关于绑定数据更改时Winforms列表框不更新的主要内容,如果未能解决你的问题,请参考以下文章
DataGrid 数据绑定/更新中的 WPF 组合框不起作用