WPF更新后台线程中的绑定

Mar*_*ark 17 data-binding wpf multithreading

我有一个控件,其数据绑定到标准ObservableCollection,我有一个后台任务调用服务来获取更多数据.

然后,我想在我的控件后面更新我的支持数据,同时显示"请稍候"对话框,但是当我将新项目添加到集合时,UI线程会在重新绑定和更新我的控件时锁定.

我可以解决这个问题,以便我的动画和内容继续在我的"请稍候"对话框中运行吗?

或者至少给用户"外观"它没有锁定?

Bub*_*rap 18

如果我理解正确,您已经使用BackgroundWorker来检索数据,而只是将此数据分配给ObservableCollection就是锁定UI.

避免锁定UI的一种方法是通过排队多个调度程序方法将数据分配给较小的块中的ObservableCollection.在每个方法调用之间,可以处理UI事件.

以下将一次添加一个项目,这有点极端,但它说明了这个概念.

void UpdateItems()
{
    //retrievedItems is the data you received from the service
    foreach(object item in retrievedItems)
        Dispatcher.BeginInvoke(DispatcherPriority.Background, new ParameterizedThreadStart(AddItem), item);    
}

void AddItem(object item)
{
    observableCollection.Add(item);
}
Run Code Online (Sandbox Code Playgroud)

  • 不,您将它们添加到调度程序线程中,但具有较低的优先级和较小的chucnks,因此UI保持响应 (3认同)

Ser*_*ich 10

ObservableCollection将引发CollectionChanged事件,这将强制UI重新绑定数据,测量,排列和重绘.如果您有许多更新,这可能会花费很多时间.

通过在小包中分割作业,可以使用户认为UI是活的.从UI线程使用Dispatcher(任何控件都引用它)来安排10-100项的集合更新操作(通过实验确定数量,这些只是为了支持这个想法).

您的后台代码可能如下所示:

void WorkInBackground()
{
    var results = new List<object>();

    //get results...

    // feed UI in packages no more than 100 items
    while (results.Count > 0)
    {
        Application.Current.MainWindow.Dispatcher.BeginInvoke(
            new Action<List<object>>(FeedUI),
            DispatcherPriority.Background,
            results.GetRange(0, Math.Min(results.Count, 100)));
        results.RemoveRange(0, Math.Min(results.Count, 100));
    }
}
void FeedUI(List<object> items)
{
    // items.Count must be small enough to keep UI looks alive
    foreach (var item in items)
    {
        MyCollection.Add(item);
    }
}
Run Code Online (Sandbox Code Playgroud)