如何仅从 WPF MVVM 中的调度程序线程以外的线程更新可观察集合中的属性? [英] How to update only a property in an observable collection from thread other than dispatcher thread in WPF MVVM?

查看:15
本文介绍了如何仅从 WPF MVVM 中的调度程序线程以外的线程更新可观察集合中的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 Employeeclass.我只需要从当前调度程序线程以外的线程更新属性 Status:

I am having a class named Employee. I need to update only the property Status from thread other than current dispatcher thread:

class Employee
{
    public string Name { get; set; }
    public string Status { get; set; }
}

Viewmodel(ViewModelBase 实现了 INotifyPropertyChanged 接口):

Viewmodel (ViewModelBase implements INotifyPropertyChanged interface):

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }


public class DisplayViewModel : ViewModelBase
{

    public static event EventHandler OnStatusChanged;

    ObservableCollection<Employee> _dailyEmployees;

    public ObservableCollection<Employee> DailyEmployees
    {
        get { return _dailyEmployees; }
        set
        {
            _dailyEmployees = value;
            OnPropertyChanged();
        }
    }

    public DisplayViewModel()
    {
        OnStatusChanged += DisplayViewModel_OnStatusChanged;
    }

    //invoked in other thread
    private void DisplayViewModel_OnStatusChanged(object sender, EventArgs e)
    {
        var d = sender as Employee;
        if (d == null)
            return;
        var em = DailyEmployees.FirstOrDefault(a => a.Name == d.Name);

        if(em == null)
        {
            DailyEmployees.Add(em);
        }
        else
        {
            em.Status = d.Status;
        }
    }
}

当我尝试向 observable 集合添加值时,它抛出异常

When i tried adding values to observable collection it throws exception as

这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection"

"This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread"

我该如何进行?谢谢.

推荐答案

要么使用dispatcher调用UI线程上的Add方法:

Either use the dispatcher to call the Add method on the UI thread:

Application.Current.Dispatcher.BeginInvoke(() => DailyEmployees.Add(em)); 

或者在 UI 线程上调用 BindingOperations.EnableCollectionSynchronization 方法使集合能够在多个线程上使用:

Or call the BindingOperations.EnableCollectionSynchronization method on the UI thread to enable the collection to be used on multiple threads:

public class DisplayViewModel
{
    private readonly ObservableCollection<Employee> _dailyEmployees = new ObservableCollection<Employee>();
    private readonly object _lock = new object();

    public ObservableCollection<Employee> DailyEmployees
    {
        get { return _dailyEmployees; }
    }

    public DisplayViewModel()
    {
        System.Windows.Data.BindingOperations.EnableCollectionSynchronization(_dailyEmployees, _lock);
        OnStatusChanged += DisplayViewModel_OnStatusChanged;
    }

    //invoked in other thread
    private void DisplayViewModel_OnStatusChanged(object sender, EventArgs e)
    {
        var d = sender as Employee;
        if (d == null)
            return;
        var em = DailyEmployees.FirstOrDefault(a => a.Name == d.Name);

        if (em == null)
        {
            DailyEmployees.Add(em);
        }
        else
        {
            em.Status = d.Status;
        }
    }
}

另请注意,Employee 类应实现 INotifyPropertyChanged 接口并为 Status 引发 PropertyChanged 事件属性,如果你想在设置的时候在视图中反映这个值.

Also note that the Employee class should implement the INotifyPropertyChanged interface and raise the PropertyChanged event for the Status property if you want the value of this one to be reflected in the view when you set it.

这篇关于如何仅从 WPF MVVM 中的调度程序线程以外的线程更新可观察集合中的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆