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

查看:152
本文介绍了如何仅从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;
        }
    }
}

当我尝试向可观察的集合中添加值时,它会抛出

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"

我应该如何进行?谢谢.

How shall I proceed? Thanks.

推荐答案

可以使用分派器在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天全站免登陆