考虑下面的对象,WPF MVVM应用程序的一部分:通知视图模型,一个集合中的对象已被选定
public class MyObject : INotifyPropertyChanged
{
// INotifyPropertyChanged gubbins
private bool _isSelected;
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
及其以下视图模型使用:
public class MyViewModel : INotifyPropertyChanged
{
// INotifyPropertyChanged gubbins
private List<MyObject> _myObjects;
public List<MyObject> MyObjects
{
get
{
return _myObjects;
}
set
{
_myObjects = value;
OnPropertyChanged("MyObjects");
}
}
public bool CanDoSomething
{
get
{
return MyObjects.Where(d => d.IsSelected).Count() > 0;
}
}
}
在在这种情况下,我可以跟踪哪些对象已被选中,并选择它们将触发OnPropertyChanged,因此可以通知父视图。
但是,CanDoSomething将始终是错误的,因为我无法触发OnPropertyChanged来创建通知。如果我把它放在MyObject中,它不知道有关该属性的任何内容,因此什么也不知道。没有地方可以将它放入ViewModel中,因为当列表中的对象被选中时没有任何反应。
我试着用ObservableCollection和自定义的“TrulyObservableCollection”(请参阅Notify ObservableCollection when Item changes)替代列表,但都无效。
我怎样才能避免点击事件呢?
你可以在MyViewModel中为所有的MyObjects绑定'PropertyChangedEvent',当Model上的IsSelected'属性被改变时它会通知ViewModel,然后你可以为'CanDoSomething提出另一个属性改变的事件表明这可能已经改变了。 –
这基本上是如何在ViewModels之间进行通信的问题。一种方法是传递给每个父项ViewModel,所以你可以在'IsSelected'设置器中调用父ViewModel的方法。其他可能的方法(应该更多)是使用静态事件,它由IsSelected设置器触发,在您的父ViewModel中订阅此事件并在处理器NotifyPropertyChanged(nameof(CanDoSomething))中调用。 – Sinatr
好点,Sinatr。在这篇文章中,Matt Hamilton将父ViewModel注入为一个宿主对象。在没有父级的情况下,子ViewModel确实不能存在的情况下,这是可以接受的(例如在没有父级时间轴的情况下为Tweet)。 http://matthamilton.net/nested-viewmodels – Christoph