WPF中的嵌套视图模型

时间:2016-08-07 16:32:26

标签: c# wpf mvvm

仍在尝试学习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处理该事件以发送相应的通知?

任何提示赞赏。

1 个答案:

答案 0 :(得分:2)

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

因此,当您将DataContext设置为主要ViewModel 时,其所有内容将订阅NotifyPropertyChanged事件,从而实现INotifyPropertyChanged接口将通知其他派生的ViewModel。

我建议您使用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();
          }
      }
}

因此您的主ViewModel看起来应该是这样的:

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

编辑:您无法绑定到字段,WPF无法解析字段。它只能处理属性。因此,通过创建子ViewModel的纯字段,您将无法在哪里获得。将这些更改为属性,您将能够通过属性名称在View中访问其内容。