简体   繁体   English

WPF中的嵌套视图模型

[英]Nested view model in WPF

Still trying to learn MVVM and WPF here. 仍然尝试在此处学习MVVM和WPF。

I'm trying to create a complex view model EditArticleViewModel . 我正在尝试创建一个复杂的视图模型EditArticleViewModel It has some code that is repeated for similar controls and so I've moved the repeating code into another class. 它有一些针对相似控件重复的代码,因此我将重复的代码移到了另一个类中。 Then, I've added several instances of that other class into EditArticleViewModel . 然后,我将另一个类的几个实例添加到EditArticleViewModel

I will set an instance of EditArticleViewModel as my window's DataContext . 我将把EditArticleViewModel的实例设置为窗口的DataContext And I will bind to things like Categories.Items and Subcategories.SelectedItem . 我将绑定到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

}

As you can see, my EditArticleViewModel class implements INotifyPropertyChanged so that I can notify the visual elements when something has changed. 如您所见,我的EditArticleViewModel类实现了INotifyPropertyChanged以便在发生更改时可以通知可视元素。

My question is about how I notify visual elements about changes within CategoryView and SubcategoryView . 我的问题是关于如何通知视觉元素有关CategoryViewSubcategoryView更改的信息。 Is there a way to notify the window about changes within these classes directly? 有没有一种方法可以直接向窗口通知这些类中的更改? Or must I raise an event from each class and have EditArticleViewModel handle that event in order to send the appropriate notification? 还是我必须从每个类中引发一个事件并让EditArticleViewModel处理该事件才能发送适当的通知?

Any tips appreciated. 任何提示表示赞赏。

There should only be one ViewModel per View, with an extend that primary ViewModel can contain other "ViewModels". 每个视图只能有一个ViewModel,并且扩展方式是主ViewModel可以包含其他“ ViewModel”。

So when you set DataContext to your primary ViewModel all the content of it will be have a subscription to NotifyPropertyChanged event, thus implementing INotifyPropertyChanged interface in other derived ViewModel will be notified. 因此,当您将DataContext设置为主ViewModel时,其所有内容将具有对NotifyPropertyChanged事件的订阅,因此将通知在其他派生的ViewModel中实现INotifyPropertyChanged接口。

I would suggest implementing a base class with INotifyPropertyChanged interface which you could derive from in your other ViewModels. 我建议使用INotifyPropertyChanged interface实现基类,您可以从其他ViewModel中派生该interface

By having this alteration you should solve the problem you are having: 通过进行此更改,您应该解决您遇到的问题:

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

Regarding ObservableCollection . 关于ObservableCollection It will notify view to change only when you add/remove items but it does not notify when content is changed. 仅当您添加/删除项目时,它才会通知视图更改,但是当内容更改时,它不会通知。 To update view on item content change you should have something like that: 要更新有关项目内容更改的视图,您应该具有以下内容:

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

And thus your Main ViewModel should look something like this: 因此,您的Main ViewModel应该看起来像这样:

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

EDIT: You cannot bind to fields, WPF does not resolve fields. 编辑:您不能绑定到字段,WPF不能解析字段。 It can only handle properties. 它只能处理属性。 So by creating plain fields of child ViewModels you are getting no where. 因此,通过创建子ViewModel的纯字段,您将无处可寻。 Change these into properties and you will be able to access its content in the View by the property name. 将它们更改为属性,您将可以通过属性名称在视图中访问其内容。

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

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