MVVM-绑定到聚合属性 [英] MVVM - binding to aggregated property
问题描述
我有以下视图模型:
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; }
...
}
xaml:
<ListBox ItemsSource="{Binding Items}" ..>
如果我想显示文本"Valid item"
如果A.Valid
和B.Valid
均为true
,则:
If I want to display text "Valid item"
if both A.Valid
and B.Valid
are true
, then:
-
我可以通过在视图(项目数据模板)中使用逻辑来做到这一点,例如使用可见性和额外的容器:
I can do this by having logic in the view (item data template), e.g using visibility and extra container:
<Grid Visibility="{Binding A.Valid}" Converter=...>
<TextBlock Text="Valid item" Visibility="{Binding B.Valid}" Converter=... \>
</Grid>
或者我可以向项目viewmodel添加新属性:
Or I can add a new property to item viewmodel:
public class Item: INotifyPropertyChanged
{
public bool Valid => A.Valid && B.Valid; // bind to this
...
}
问题在于SubItem
中的任何一个的通知都不会更新视图.
The problem is that notifications of either of SubItem
will not update the view.
在(1)的情况下,绑定将同时预订PropertyChanged
事件:Item
和相应的SubItem
.在(2)的情况下,绑定仅了解Item.Valid
属性,因此我必须执行以下操作:
In case of (1) the binding will subscribe to both PropertyChanged
events: Item
and corresponding SubItem
. In case of (2) the binding only knows about Item.Valid
property, so I have to do something like:
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)(有时使用数据触发器,但这无关紧要).
Which is awful. So I prefer (1) (using data triggers sometimes, but it's irrelevant).
是否还有其他选项可以真正拥有viewmodel属性(2)但没有麻烦?
Are there other options to actually have viewmodel property (2) but without the hassle?
推荐答案
在这种特殊情况下,数据绑定方法似乎最简单.这样,您就可以依靠WPF的数据绑定机制为您处理事件订阅,而不必通过代码手动进行.
The data binding approach seems easiest in this particular case. That way you rely upon WPF's data binding mechanism handling the event subscriptions for you, rather than having to do it manually via code.
我知道处理此问题的唯一其他方法是使用某种中介对象.更改SubItem
的Valid
属性时,您会发出一条消息,表明已发生这种情况.预订此消息的Item
类通过检查A
和B
的当前有效状态来处理该消息,然后相应地设置其自己的Valid
属性.
The only other way I know of handling this is to use some kind of mediator object. When the Valid
property of SubItem
is changed you send out a message that this has happened. Your Item
class, which has subscribed to this message, handles it by checking the current valid state of A
and B
, then sets its own Valid
property accordingly.
但是,这种方法并非没有它自己的皱纹.一方面,您需要将中介对象注入到ViewModel对象中.同样,您的Item
对象也需要在适当的时间(通常是在对象创建和销毁时)订阅和取消订阅相关消息.尽管比直接处理属性更改事件要容易得多,但所有这些工作要比仅使用数据触发器并依赖WPF的绑定机制IMO更加困难.
This approach is not without its own wrinkles however. For one thing, you need to inject the mediator object into your ViewModel objects. Also your Item
objects need to subscribe to and unsubscribe from the relevant message at the appropriate times (usually on object creation and destruction). All of this plumbing, while still easier than handling property changed events directly, is more difficult than just using a data trigger and relying on WPF's binding mechanism IMO.
这篇关于MVVM-绑定到聚合属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!