WPF多线程:我能在非UI线程中更新控件的数据上下文吗?

9

我们能否在非UI线程中更新WPF控件的数据上下文?

假设我们有一个Label,其数据上下文为MyClass,并将Content绑定到MyProperty

<Label Name="label" Content="{Binding MyProperty}" />,

其中MyClass仅为:

public class MyClass : INotifyPropertyChanged
{
    int _myField;
    public int MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
            PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

在非UI线程中,我们可以使用myClass.MyProperty = "updated"来更新标签的内容,但是我们不能直接使用label.Content = "updated"。这个说法正确吗?
我的答案:
以下是我找到的结论:
- 从非UI线程中,您无法更新控件; - 从非UI线程中,您可以更新控件数据上下文的属性; - 从非UI线程中,您无法向绑定到控件的ObservableCollection添加或删除项目。但是有一个解决方法:http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx
1个回答

4
是的,这是正确的。对于集合还有其他的注意事项(CollectionChanged 事件必须在 UI 线程中执行)。
通常情况下,您使用 ObservableCollection<T> 来绑定到集合。如果您从非 UI 线程更新此集合,则代码将会出现问题,因为事件是从它们所在的同一线程触发的(ObservableCollection<T> 在集合发生更改时触发事件)。为了绕过这个问题,您需要为自定义实现的 ObservableCollection<T> 提供委托,以在 UI 线程中触发事件(使用 Dispatcher)。

请问您能否提供有关集合的更多细节?谢谢。 - Shuo
谢谢,我想我在这里找到了一个解决方案:http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx - Shuo
我也用过那个,但有些情况下代码不起作用(一些WPF对象不继承自DispatcherObject)。 - Femaref
那么,你能分享任何更好的解决方案吗? - Shuo
好的,我的也不是很理想 - DispatcherInvokeBeginInvoke 作为成员,你可以将它们提供给你的 ViewModel,然后再提供给你的集合。 - Femaref

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接