2016-08-07 3 views
0

По-прежнему пытается узнать MVVM и WPF здесь.Вложенная модель в WPF

Я пытаюсь создать сложную модель вида EditArticleViewModel. У этого есть некоторый код, который повторяется для аналогичных элементов управления, и поэтому я переместил повторяющийся код в другой класс. Затем я добавил несколько экземпляров этого другого класса в EditArticleViewModel.

Я установил экземпляр EditArticleViewModel в качестве моего окна DataContext. И я буду привязываться к вещам вроде Categories.Items и Subcategories.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, чтобы я мог уведомить визуальные элементы, когда что-то изменилось.

Мой вопрос о том, как я уведомляю визуальные элементы об изменениях в пределах CategoryView и SubcategoryView. Есть ли способ напрямую уведомлять окно об изменениях в этих классах? Или я должен поднимать событие из каждого класса и иметь EditArticleViewModel обрабатывать это событие, чтобы отправить соответствующее уведомление?

Любые советы, оцененные.

+1

Не могли бы вы использовать 'SubcategoryView' и' CategoryView' для реализации 'INotifyPropertyChanged', и просто разрешите представление обрабатывать изменения? – Michael

+0

@Michael: Но тогда мне не нужно было устанавливать DataContext для этих экземпляров класса? –

+0

@JonathanWood Если привязка может найти заданное свойство на заданном объекте, разве вы не думаете, что он также может найти объект, на котором он нашел свойство? Бросьте проблемы с заимствованием и напишите какой-то тривиальный код, чтобы играть с этим материалом. Скоро у вас будет много реальных вопросов. –

ответ

2

Должен быть только один ViewModel для каждого вида с расширением, в котором основной ViewModel может содержать другие «ViewModels».

Итак, когда вы установили DataContext к основному ViewModel все содержание этого будет иметь подписку на NotifyPropertyChanged событие, таким образом, реализует интерфейс INotifyPropertyChanged в других полученных ViewModel будет уведомлен.

Я бы предложил реализовать базовый класс с INotifyPropertyChangedinterface, который вы могли бы получить в других моделях ViewModels.

Имея это изменение вы должны решить эту проблему вы испытываете:

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

EDIT: Вы не можете связываться с полями, WPF не разрешает поля. Он может обрабатывать только свойства. Таким образом, создавая простые поля дочерних ViewModels, вы ничего не получаете. Измените их в свойствах, и вы сможете получить доступ к его содержимому в представлении по имени свойства.

+0

Я не совсем понимаю это. Таким образом, реализация «INotifyPropertyChanged» в моих дочерних классах достаточно тривиальна. Но я пытаюсь понять, как эти уведомления распространяются на родительский класс «EditArticleView». Я не вижу ответа на это в вашем коде. –

+0

Если вы хотите уведомить об изменениях в своих дочерних ViewModels, вы должны реализовать интерфейс INotifyPropertyChanged в этих дочерних ViewModels. View увидит реализацию и подписаться на событие NotifyPropertyChanged. – Karolis

Смежные вопросы