我有一个名为Employee 的类。我只需要从当前调度程序线程以外的线程更新属性 Status:
class Employee
{
public string Name { get; set; }
public string Status { get; set; }
}
Viewmodel(ViewModelBase 实现了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;
}
}
}
当我尝试向可观察集合添加值时,它抛出异常
“这种类型的 CollectionView 不支持从与 Dispatcher 线程不同的线程更改其 SourceCollection”
我该如何进行?谢谢。
请您参考如下方法:
要么使用调度器在 UI 线程上调用 Add 方法:
Application.Current.Dispatcher.BeginInvoke(() => DailyEmployees.Add(em));
或调用BindingOperations.EnableCollectionSynchronization UI 线程上的方法,使集合能够在多个线程上使用:
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 接口(interface)并为 Status 引发 PropertyChanged 事件属性,如果你希望这个的值在你设置它时反射(reflect)在 View 中。
