我有以下 View 模型:
public class ViewModel: INotifyPropertyChanged
{
public ObservableCollection<Item> Items { get; set; }
...
}
public class Item: INotifyPropertyChanged
{
public SubItem A { get; set; }
public SubItem B { get; set; }
...
}
public class SubItem: INotifyPropertyChanged
{
public bool Valid { get; set; }
...
}
xml:
<ListBox ItemsSource="{Binding Items}" ..>
如果我想显示文字
"Valid item"
如果两者都是 A.Valid
和 B.Valid
是 true
, 然后:<Grid Visibility="{Binding A.Valid}" Converter=...>
<TextBlock Text="Valid item" Visibility="{Binding B.Valid}" Converter=... \>
</Grid>
public class Item: INotifyPropertyChanged
{
public bool Valid => A.Valid && B.Valid; // bind to this
...
}
问题是
SubItem
中的任何一个的通知不会更新 View 。 在 (1) 的情况下,绑定(bind)将订阅
PropertyChanged
事件:Item
和相应的SubItem
.在 (2) 的情况下,绑定(bind)只知道 Item.Valid
属性(property),所以我必须做类似的事情:public class Item: INotifyPropertyChanged
{
SubItem _a;
public SubItem A
{
get { return _a; }
set
{
_a.PropertyChanged -= bla;
_a = value;
_a.PropertyChanged += bla;
OnPropertyChanged(nameof(A));
OnPropertyChanged(nameof(Valid));
}
}
void bla(object sender, PropertyChangedEventArgs e) =>
OnPropertyChanged(nameof(Valid));
...
}
这太可怕了。所以我更喜欢(1)(有时使用数据触发器,但这无关紧要)。
是否有其他选项可以实际拥有 viewmodel 属性 (2) 但没有麻烦?
最佳答案
在这种特殊情况下,数据绑定(bind)方法似乎最简单。这样,您就可以依靠 WPF 的数据绑定(bind)机制为您处理事件订阅,而不必通过代码手动完成。
我知道的唯一其他处理方法是使用某种中介对象。当Valid
SubItem
的属性(property)发生了变化,您会发出一条消息,表明这已发生。您的 Item
订阅此消息的类通过检查 A
的当前有效状态来处理它和 B
, 然后设置自己的 Valid
相应的属性(property)。
然而,这种方法并非没有其自身的缺陷。一方面,您需要将中介对象注入(inject)到您的 ViewModel 对象中。还有你的Item
对象需要在适当的时间订阅和取消订阅相关消息(通常在对象创建和销毁时)。所有这些管道虽然仍然比直接处理属性更改事件更容易,但比仅使用数据触发器和依赖 WPF 的绑定(bind)机制 IMO 更困难。
关于c# - MVVM - 绑定(bind)到聚合属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48930678/