我有一个名为class
的{{1}}。我只需要更新当前调度程序线程以外的线程的属性Employee
:
Status
Viewmodel(class Employee
{
public string Name { get; set; }
public string Status { get; set; }
}
继承自ViewModelBase
界面):
inotifypropertychanged
公共类DisplayViewModel:ViewModelBase {
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
当我尝试向可观察的集合中添加值时,它会抛出
异常“这种类型的CollectionView不支持从与Dispatcher线程不同的线程对其SourceCollection进行更改”
我应该如何进行?谢谢。
答案 0 :(得分:2)
使用分派器在UI线程上调用Add
方法:
Application.Current.Dispatcher.BeginInvoke(() => DailyEmployees.Add(em));
或在UI线程上调用BindingOperations.EnableCollectionSynchronization方法以使集合可以在多个线程上使用:
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
接口并为PropertyChanged
属性引发Status
事件在视图中进行设置。
答案 1 :(得分:1)
您的代码中有一个大问题。首先,ObservableCollection已经是一个通知更改的集合,因此您无需重新初始化它,只需调用Clear和Add / Insert。
第二,Employee类应为ViewModelBase:
class Employee: ViewModelBase
{
private string _status;
public string Name { get; set; }
public string Status
{
get
{
return _status;
}
private set
{
_status=value;
RaisePropertyChanged("Status");
}
}
}
这应该允许您更改DailyEmployees[0].Status="NewStatus";
LE:如果从其他线程更改数据时遇到问题,请检查以下链接:Using BindingOperations.EnableCollectionSynchronization
LLE:我将ViewModelBase
类用于Employee
,因为它已在代码示例中使用。原始答案意味着实现class Employee: INotifyPropertyChanged
和实现所需的方法。
答案 2 :(得分:0)
尝试Application.Current.Dispatcher.BeginInvoke(() => /* update value */);