对依赖/嵌套视图模型的属性触发INotifyPropertyChanged.PropertyChanged

时间:2016-06-27 21:14:25

标签: wpf binding inotifypropertychanged

我有一个嵌套的视图模型结构,如下例所示:

public class SubViewModel : INotifyPropertyChanged
{
    public string Property
    {
        get
        {
            // calculate result and return it
        }
    }
}

public class ViewModel : INotifyPropertyChanged
{
    public SubViewModel Sub { get; set; }

    public void MyMethod()
    {
        // executes code that changes some parameters such that Sub.Property changes

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Sub.Property"));
    }
}

在父视图模型中发生更改会影响嵌套视图模型的属性。换句话说,子视图模型上的属性(示例中为SubViewModel.Property)会更改,但子视图模型不会知道。

我希望以告诉WPF绑定引擎的方式调用PropertyChanged子视图模型Property上的属性Sub已更改。我尝试了以下所有选项,但到目前为止还没有任何选项:

OnPropertyChanged("");
OnPropertyChanged("*");
OnPropertyChanged("Sub");
OnPropertyChanged("Sub.Property");
OnPropertyChanged("Sub.*");

有没有办法实现这个目标?

请注意:我知道父视图模型可以在子视图模型上调用一个方法,该方法在子视图模型上引发PropertyChanged事件。我有理由不这样做。

3 个答案:

答案 0 :(得分:0)

  • 更改SubViewModel时调用OnPropertyChanged。
  • 您的SubviewModel应该在MainViewModel中创建
  • 在您的视图中,您必须调用:“DataContext = {Binding Sub}”
  • 在你的SubView中,MUSTNOT是“DataContext”的一个词
  • 在SubView中,您必须绑定如下属性: “Example = {Binding MyProperty}”

    public class SubViewModel : INotifyPropertyChanged
    {
       private string _MyProperty;
       public string MyProperty
       {
           get { return _MyProperty; }
           set { _MyProperty = value;
               NotifyPropertyChanged();
           }
       }
    
       #region NotifyPropertyChanged
       public event PropertyChangedEventHandler PropertyChanged;
       private void NotifyPropertyChanged([CallerMemberName] string info = null)
       {
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
       }
       #endregion
    }
    
    public class ViewModel : INotifyPropertyChanged
    {
       private SubViewModel _Sub;
       public SubViewModel Sub
       {
           get { return _Sub; }
           set { _Sub = value;
            NotifyPropertyChanged();
           }
       }
    
       public void MyMethod()
       {
        // executes code that changes some parameters such that Sub.Property changes
    
           NotifyPropertyChanged();
       }
    
       #region NotifyPropertyChanged
       public event PropertyChangedEventHandler PropertyChanged;
       private void NotifyPropertyChanged([CallerMemberName] string info = null)
       {
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
       }
    
       #endregion
    }
    

答案 1 :(得分:0)

您正在ViewModelSubViewModel之间创建循环依赖关系。这导致两者之间的强耦合,这从来都不是好事。我提出了另一种解决方案。 INotifyPropertyChanged已经为基础设施提供了您想要的功能。

因此SubViewModel依赖于ViewModel。我认为它需要ViewModel的一个属性的值来计算SubViewModel.Property的值。因此,解决方案很自然地将SubViewModelViewModel.PropertyChanged联系起来:

public class SubViewModel : INotifyPropertyChanged
{
    private ViewModel parent;

    public event PropertyChangedEventHandler PropertyChanged;

    public SubViewModel(ViewModel parent)
    {
        this.parent = parent;
        // Hook up to parent's property changes.
        this.parent.PropertyChanged += (sender, e) => 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SubProperty"));
    }

    public string SubProperty
    {
        get { return parent.Property; }
    }
}

注意如何在ViewModel的construcor中期望SubViewModel来明确依赖关系。这样,下一个程序员立即看到SubViewModel需要ViewModel才能正常工作,并且无法构建无效的SubViewModel

构造函数中定义的事件处理程序当然非常简化。最好使它成为一个私有方法,在它执行任何操作之前检查e.PropertyName。无论如何,它的基本目的是通知所有订阅SubViewModel属性更改的客户,因为ViewModel.Property已经更改了。{/ p>

您最好没有从ViewModelSubViewModel的关系,以避免循环依赖。摆脱Sub属性并实现ViewModel,如下所示:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string property;
    public string Property
    {
        get { return this.property; }
        set
        {
            this.property = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Property"));
        }
    }
}

请注意ViewModel的实现与任何其他INotifyPropertyChanged实现完全相同。父母不需要知道孩子的价值观。只有ViewModel的客户端实现处理ViewModel属性更改的逻辑,父级。

以下是测试的工作示例:https://dotnetfiddle.net/vQJBak

答案 2 :(得分:0)

SubViewModel中创建一个事件,并在发生变化时引发该事件。父视图模型将订阅该事件。

这是什么事件。