简体   繁体   English

MVVM-绑定到聚合属性

[英]MVVM - binding to aggregated property

I have following viewmodels: 我有以下视图模型:

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: xaml:

<ListBox ItemsSource="{Binding Items}" ..>

If I want to display text "Valid item" if both A.Valid and B.Valid are true , then: 如果我想在A.ValidB.Valid均为true下显示文本"Valid item" ,则:

  1. I can do this by having logic in the view (item data template), eg using visibility and extra container: 我可以通过在视图(项目数据模板)中使用逻辑来做到这一点,例如使用可见性和额外的容器:

     <Grid Visibility="{Binding A.Valid}" Converter=...> <TextBlock Text="Valid item" Visibility="{Binding B.Valid}" Converter=... \\> </Grid> 
  2. Or I can add a new property to item viewmodel: 或者,我可以向项目viewmodel添加新属性:

     public class Item: INotifyPropertyChanged { public bool Valid => A.Valid && B.Valid; // bind to this ... } 

    The problem is that notifications of either of SubItem will not update the view. 问题在于,任一SubItem通知都不会更新视图。

In case of (1) the binding will subscribe to both PropertyChanged events: Item and corresponding SubItem . 在(1)的情况下,绑定将同时订阅PropertyChanged事件: Item和相应的SubItem In case of (2) the binding only knows about Item.Valid property, so I have to do something like: 在(2)的情况下,绑定仅知道Item.Valid属性,因此我必须执行以下操作:

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));
    ...
}

Which is awful. 真可怕 So I prefer (1) (using data triggers sometimes, but it's irrelevant). 所以我更喜欢(1)(有时使用数据触发器,但这无关紧要)。

Are there other options to actually have viewmodel property (2) but without the hassle? 是否还有其他选项可以实际拥有viewmodel属性(2),但没有麻烦?

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. 这样,您就可以依靠WPF的数据绑定机制为您处理事件订阅,而不必通过代码手动进行。

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. SubItemValid属性更改时,您会发出一条消息,表明已发生这种情况。 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. 预订此消息的Item类通过检查AB的当前有效状态来处理它,然后相应地设置其自己的Valid属性。

This approach is not without its own wrinkles however. 然而,这种方法并非没有它自己的皱纹。 For one thing, you need to inject the mediator object into your ViewModel objects. 一方面,您需要将中介对象注入到ViewModel对象中。 Also your Item objects need to subscribe to and unsubscribe from the relevant message at the appropriate times (usually on object creation and destruction). 此外,您的Item对象还需要在适当的时间(通常在对象创建和销毁时)订阅和取消订阅相关消息。 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. 尽管比直接处理属性更改事件要容易得多,但所有这些管道比仅使用数据触发器并依赖WPF的绑定机制IMO更加困难。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM