Чтобы показать возможные отношения между Model и ViewModel, я сначала упростил ваш пример, изменив тип Occupation
на string
.Тогда PersonModel
и PersonViewModel
могут выглядеть следующим образом:
public class PersonModel : INotifyPropertyChanged
{
private string occupation;
public string Occupation
{
get
{
return this.occupation;
}
set
{
if (this.occupation != value)
{
this.occupation = value;
this.OnPropertyChanged("Occupation");
}
}
}
}
public class PersonViewModel: INotifyPropertyChanged
{
private PersonModel model;
public string Occupation
{
get
{
return this.model.Occupation;
}
set
{
this.model.Occupation = value;
}
}
public PersonViewModel(PersonModel model)
{
this.model = model;
this.model.PropertyChanged += new PropertyChangedEventHandler(model_PropertyChanged);
}
private void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.OnPropertyChanged(e.PropertyName);
}
}
Важным отличием вашей версии является то, что PersonModel
и PersonViewModel
оба реализуют INotifyPropertyChanged
.Это важно, потому что в противном случае изменение свойства PersonModel
напрямую (т. Е. Без прохождения PersonViewModel
) не будет иметь никакого эффекта в представлении.Также обратите внимание, как PropertyChangedEvent
из модели передается в представление.
Теперь предположим, что Occupation
- это не string
, а класс со своими собственными свойствами, например:
public class OccupationModel : INotifyPropertyChanged
{
private double salary;
public double Salary
{
get
{
return this.salary;
}
set
{
if (this.salary != value)
{
this.salary = value;
this.OnPropertyChanged("Salary");
}
}
}
}
Использование ViewModel между вашим View и Model дает вам некоторую гибкость при представлении ваших данных в View.Вот два варианта, как вы могли бы это сделать:
Опция 1 Предоставить свойства Occupation
непосредственно в PersonViewModel
.Это простое решение, поскольку вам не нужно реализовывать другую ViewModel.
public class PersonViewModel: INotifyPropertyChanged
{
private PersonModel model;
public double OccupationSalary
{
get
{
return this.model.Occupation.Salary;
}
set
{
this.model.Occupation.Salary = value;
}
}
public PersonViewModel(PersonModel model)
{
this.model = model;
this.model.Occupation.PropertyChanged += new PropertyChangedEventHandler(occupation_PropertyChanged);
}
private void occupation_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.OnPropertyChanged("Occupation" + e.PropertyName);
}
}
Свойство OccupationSalary
предоставляет прямой доступ к свойству Salary
в Occupation
.Обратите внимание, как теперь нужно обрабатывать событие PropertyChanged
Occupation
, и что нам нужно переименовать свойство в occupation_PropertyChanged
.
Option 2 (рекомендуется). Показать свойстваот Occupation
до OccupationViewModel
.Вы должны сделать это, если вам нужно реализовать какую-либо бизнес-логику, специфичную для Occupation
.Учитывая ваш пример, это, вероятно, то, что вы намеревались сделать:
public class PersonViewModel: INotifyPropertyChanged
{
private PersonModel model;
private OccupationViewModel occupationViewModel;
public OccupationViewModel OccupationViewModel
{
get
{
return this.occupationViewModel;
}
}
public PersonViewModel(PersonModel model)
{
this.model = model;
this.occupationViewModel = new OccupationViewModel(this.model.occupation);
}
}
public class OccupationViewModel : INotifyPropertyChanged
{
private OccupationModel model;
public double Salary
{
get
{
return this.model.Salary;
}
set
{
this.model.Salary = value;
}
}
public OccupationViewModel(OccupationModel model)
{
this.model = model;
this.model.PropertyChanged += new PropertyChangedEventHandler(model_PropertyChanged);
}
private void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.OnPropertyChanged(e.PropertyName);
}
}
Как видите, OccupationViewModel
имеет точно такую же структуру, что и упрощенный PersonViewModel
, который я показал в начале.Важное отличие вашей версии OccupationViewModel
заключается в том, что она предоставляет свойства из OccupationModel
, а не OccupationModel
.