【问题标题】:How to avoid that WPF ListBox updates block buttons?如何避免 WPF ListBox 更新块按钮?
【发布时间】:2016-02-29 08:58:40
【问题描述】:

我有一个带有 ListBox 的 WPF 窗口,它绑定到 public ObservableCollection<String>,正在由另一个线程 (BackGroudWorker) 更新。

<ListBox Name="ListBox" 
         ItemsSource="{Binding MyCollection}" 
         ... />

在同一个窗口中,我有一个带有点击处理程序的Button:

<Button Content="Close"
        Click="Button_LogWindow_closeButton_Click"
        ... />

当我在更新 ListBox 时单击按钮时,通常不会调用此处理程序。虽然当后台线程完成并且ListBox 不再更新时它可以正常工作。

在我看来,按钮单击事件在调用它的处理程序之前已从队列中删除。我说的对吗?

你知道如何解决这个问题吗?

【问题讨论】:

  • Click 事件不会被移除,而是会在 ListBox 更新后排队执行。如果你做对了,就不会有按钮事件块,这可能是你的线程代码有问题(与 UI 线程同步)。
  • 不幸的是,处理程序要么被立即调用(似乎只在ListBox 更新之间工作),要么从未被调用。 BackGroundWorker 正在写信给public ObservableCollection。
  • 问题在于您的 C# 代码,而不是 XAML。如果您有兴趣修复它,请尽可能详细地发布您的 C# 代码。

标签: c# wpf multithreading listbox backgroundworker


【解决方案1】:

很难说没有看到您的代码,但是您的 GUI 线程可能在每次调用 ObservableCollection 的 Add 方法时都忙于更新 ListBox,以至于鼠标单击事件没有得到处理。

如果您的后台线程正在使用Dispatcher.Invoke 或Dispatcher.BeginInvoke 将项目添加到 ObservableCollection,您可以降低优先级(例如 Dispatcher.Background)以便让点击事件有机会被处理。

您还可以将 ObservableCollection 与添加范围方法一起使用,该方法仅针对项目集合而不是每个项目引发一次 INotifyCollectionChanged.CollectionChanged 事件。请参阅 this answer 或 Microsoft 自己的 BulkObservableCollection 作为示例。

【讨论】:

    【解决方案2】:

    我发现了错误。每次更新窗口时都会调用函数ListBox.Focus()。这似乎是为了将窗口保持在最高位置。我已将 XAML 文件更改为:

    <Window ...
        Topmost="True" 
        ... />
    

    这应该是它的本意;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      相关资源
      最近更新 更多