C# 在父视图模型中公开子视图模型的属性

C# 在父视图模型中公开子视图模型的属性,c#,wpf,mvvm,C#,Wpf,Mvvm,我的父视图模型包含两个子视图模型,它看起来像 public MainViewModel:ObservableObject { public MainViewModel(){//initalize everything}; private SomeViewModel childvm1; private AnotherViewModel childvm2; public SomeViewModel Childvm1 {

我的父视图模型包含两个子视图模型,它看起来像

public MainViewModel:ObservableObject
{
     public MainViewModel(){//initalize everything};

     private SomeViewModel childvm1;
     private AnotherViewModel childvm2;


      public SomeViewModel Childvm1
            {
                get
                {
                    return childvm1;
                }
                set
                {
                    SetField(ref childvm1, value, "Childvm1");
                }
            }

     public AnotherViewModel Childvm2
            {
                get
                {
                    return childvm2;
                }
                set
                {
                    SetField(ref childvm2, value, "Childvm2");
                }
            }

     //when this changes i want to notify childvm2 and call a function in it
     public SomeModel SelectedValueofChildvm1
            {
                get
                {
                    return Childvm1.SelectedValue;
                }
            }
}

SelectedValueofChildvm1
更改时,如何调用
childvm2
中的函数?

您必须订阅子视图模型的PropertyChangedEvent,如下所示:

public SomeViewModel Childvm1
{
    get
    {
        return childvm1;
    }
    set
    {
        if (childvm1 != null) childvm1.PropertyChanged -= OnChildvm1PropertyChanged;
        SetField(ref childvm1, value, "Childvm1");
        if (childvm1 != null) childvm1.PropertyChanged += OnChildvm1PropertyChanged;
    }
}

private coid OnChildvm1PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // now update Childvm2
}
但要小心:

  • 您可能还需要在childvm2 setter中更新childvm2
  • 您需要确保childvm1实例不超过ViewModel实例,或者在将MainViewModel返回给垃圾收集器之前,将childvm1设置为null

最简单的方法是使用
INotifyPropertyChanged
界面来侦听属性更改通知

public MainViewModel:ObservableObject
{
     public MainViewModel(){
        //initalize everything
        Childvm1.PropertyChanged += (s,e) {
            if(e.PropertyName == "SelectedValue") {
               // Do what you want
            }           
        };
    };

}

SelectedValueofChildvm1
如何改变,当没有
set
时?集合在childvm1中,我也必须在这里公开它吗?你需要对值的变化做出反应,还是你只是想让它可以绑定?@CodingGorilla我需要对它的变化做出反应所以,假设视图模型实现了
INotifyPropertyChanged
(错误的假设),只需将处理程序附加到
PropertyChanged
,并在属性更改时做出反应。这不管用吗?如果您希望子视图模型发生变化,那么这很好,如果不是,那么我的方法就简单多了。=)显然,OP希望它们发生变化,因为包含了Childvm1属性的公共setter。另外,我不知道为什么您的解决方案比这个简单得多?您没有取消订阅活动,因此您的代码少了一行,这是真的。但在这个解决方案中,订阅和取消订阅是非常对称的,它们所属的属性也很好,不那么脆弱。这不是批评,我的观点是,如果他不希望它发生变化,那么在构造函数中连接处理程序就更简单了,这样就完成了。我们看不到
设置字段
的作用,因此它完全有可能处理属性更改通知,但不允许更改特定字段(如子视图模型)。@CodingGorilla我没有将您的评论视为批评,只是讨论它以便我们和其他读者能够了解。事实上,每当我有一个
只读
字段(因此属性中没有setter)时,我自己就使用您的方法。当字段不是只读字段时,我在属性中有一个setter(可能是私有的,也可能是公共的),并在其中包含代码。关于SetField,您是对的,但我假设它是从observeObject继承的样板代码“if it change raise the event”。