Para mostrar las posibles relaciones entre modelo y modelo de vista que simplifica su primer ejemplo cambiando el tipo de Occupation
en string
. Entonces PersonModel
y PersonViewModel
podría tener este aspecto:
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);
}
}
La diferencia importante a su versión es que PersonModel
y PersonViewModel
tanto implemento INotifyPropertyChanged
. Esto es importante porque, de lo contrario, cambiar una propiedad de PersonModel
directamente (es decir, sin pasar por PersonViewModel
) no tendrá ningún efecto en la Vista. También observe cómo el PropertyChangedEvent
del Modelo se canaliza a la Vista.
Ahora supongamos Occupation
no es una sino una clase string
con sus propias propiedades, por ejemplo:
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");
}
}
}
}
El uso de un modelo de vista entre su visión y modelo le da cierta flexibilidad en la forma de presentar los datos a la vista . Aquí hay dos opciones de cómo se puede hacer esto:
Opción 1 Exponer las propiedades de Occupation
directamente en la PersonViewModel
. Esta es una solución simple porque no necesita implementar otro 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);
}
}
La propiedad OccupationSalary
da acceso directo a la propiedad Salary
en Occupation
. Observe cómo ahora se debe manejar el evento PropertyChanged
de Occupation
, y que tenemos que cambiar el nombre de la propiedad en occupation_PropertyChanged
.
Opción 2 (recomendado) Exponer las propiedades de Occupation
a través de un OccupationViewModel
. Debe hacer esto si necesita implementar cualquier lógica comercial específica al Occupation
. Dada su ejemplo, esto es probablemente lo que pretende hacer:
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);
}
}
Como se puede ver OccupationViewModel
tiene exactamente la misma estructura que el simplificada PersonViewModel
he mostrado en el principio. La diferencia importante con su versión de OccupationViewModel
es que expone las propiedades de OccupationModel
, no OccupationModel
.
¿Por qué es PersonViewModel.Occupation una propiedad de escritura? Normalmente sería de solo lectura, después de todo, ¿quién lo configurará? –
Estaba pensando en exponerlo para que algún otro modelo de vista pueda cambiarlo. ¿O es aquí donde entra algún método o comando? Por cierto, soy un novato de WPF, MVVM. – Patrick
Patrick Creo que lo que Joe está diciendo es que el modelo de vista se puede modificar externamente sin configurarlo (accediendo a sus propiedades): 'personViewModel.Occupation.Occupation = new OccupationModel (" ingeniero de software ");' – Jay