【问题标题】:Nested view model in WPFWPF中的嵌套视图模型
【发布时间】:2016-08-07 16:32:26
【问题描述】:

这里还在尝试学习 MVVM 和 WPF。

我正在尝试创建一个复杂的视图模型EditArticleViewModel。它有一些针对类似控件重复的代码,因此我将重复代码移到了另一个类中。然后,我将其他类的几个实例添加到EditArticleViewModel

我会将EditArticleViewModel 的实例设置为我的窗口的DataContext。我会绑定到Categories.ItemsSubcategories.SelectedItem 之类的东西。

public class CategoryView
{
    public ObservableCollection<object> Items { /* */ }
    public object SelectedItem { /* ... */ }
}

public class SubcategoryView
{
    public ObservableCollection<object> Items { /* */ }
    public object SelectedItem { /* ... */ }
}

public class EditArticleViewModel : INotifyPropertyChanged
{
    public CategoryView Categories { get; private set; }
    public SubcategoryView Subcategories { get; private set; }

    public EditArticleViewModel()
    {
        Categories = new CategoryView();
        SubcategoryView Subcategories new SubcategoryView();
    }

    // Additional properties and methods here

}

如您所见,我的EditArticleViewModel 类实现了INotifyPropertyChanged,以便在发生变化时通知可视元素。

我的问题是关于如何通知视觉元素 CategoryViewSubcategoryView 的变化。有没有办法直接通知窗口这些类中的变化?还是我必须从每个班级引发一个事件并让EditArticleViewModel 处理该事件才能发送适当的通知?

感谢任何提示。

【问题讨论】:

  • 能否让SubcategoryViewCategoryView 实现INotifyPropertyChanged 并让视图处理更改?
  • @Michael:但是我不需要将DataContext 设置为这些类实例吗?
  • @JonathanWood 如果绑定可以在给定对象上找到给定属性,您不认为它也可以找到它找到该属性的对象吗?放弃借用的麻烦,写一些琐碎的代码来玩这些东西。你很快就会有很多真正的问题。
  • @EdPlunkett:说什么?它可以很好地找到对象。我的问题是关于传播通知。这一定很常见,我正在尝试了解人们如何处理它。如果你的目的是批评而不是帮助,请不要回答我的问题。
  • @JonathanWood。目的。哪一个。拥有。这。财产。是。什么。它。得到。这。通知。从。除非您搞砸并忽略正确实施 INotifyPropertyChanged。为什么要传播通知?为什么要增加不必要的复杂性?

标签: c# wpf mvvm


【解决方案1】:

每个 View 应该只有一个 ViewModel,主 ViewModel 可以包含其他“ViewModel”的扩展。

因此,当您将 DataContext 设置为您的主 ViewModel 所有内容 将订阅 NotifyPropertyChanged 事件,因此在其他派生 ViewModel 中实现 INotifyPropertyChanged 接口将得到通知.

我建议使用 INotifyPropertyChanged interface 实现一个基类,您可以从其他 ViewModel 中派生该基类。

通过此更改,您应该可以解决您遇到的问题:

public class ObservableViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName]string propName = null)
    {
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

public class CategoryView : ObservableViewModelBase
{
  public ObservableCollection<object> Items { /* */ }
  public object SelectedItem { /* ... */ }
}

public class SubcategoryView : ObservableViewModelBase
{
  public ObservableCollection<object> Items { /* */ }
  public object SelectedItem { /* ... */ }
}

public class EditArticleView : ObservableViewModelBase
{
  public CategoryView Categories { get; set; } = new CategoryView();
  public SubcategoryView Subcategories { get; set; } = new SubcategoryView();
}

关于ObservableCollection。它只会在您添加/删除项目时通知视图更改,但在内容更改时不会通知。要更新项目内容更改的视图,您应该有类似的内容:

public class GridRowItemViewModel : ObservableViewModelBase // From previous example.
{
      private string _sampleProp;          
      public string SampleProp
      {
          get
          {
              return _sampleProp;
          }
          set
          {
              _sampleProp = value;
              OnPropertyChanged();
          }
      }
}

因此您的 Main ViewModel 应该如下所示:

public class MainViewModel : ObservableViewModelBase // This is your DataContext.
{
     public ObservableCollection<GridRowItemViewModel> GridCollection { get; set; }
}

编辑:您不能绑定到字段,WPF 不解析字段。它只能处理属性。因此,通过创建子 ViewModel 的普通字段,您将无处可去。将这些更改为属性,您将能够通过属性名称在视图中访问其内容。

【讨论】:

  • 我不太明白这一点。所以在我的子类中实现INotifyPropertyChanged 是微不足道的。但我试图了解这些通知如何传播到父 EditArticleView 类。我在你的代码中没有看到答案。
  • 如果您想通知子 ViewModel 中的更改,您应该在这些子 ViewModel 中实现 INotifyPropertyChanged 接口。 View 将看到实现并订阅 NotifyPropertyChanged 事件。
猜你喜欢
  • 2017-04-10
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
  • 2013-07-08
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多