MVVM-绑定到聚合属性 [英] MVVM - binding to aggregated property

查看:58
本文介绍了MVVM-绑定到聚合属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下视图模型:

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.ValidB.Valid均为true,则:

If I want to display text "Valid item" if both A.Valid and B.Valid are true, then:

  1. 我可以通过在视图(项目数据模板)中使用逻辑来做到这一点,例如使用可见性和额外的容器:

  1. 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.

    我知道处理此问题的唯一其他方法是使用某种中介对象.更改SubItemValid属性时,您会发出一条消息,表明已发生这种情况.预订此消息的Item类通过检查AB的当前有效状态来处理该消息,然后相应地设置其自己的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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆