C# 维护WPF MVVM视图模型&;模型关系
这似乎是一个基本问题,但我无法找出最佳实现。如何管理两个视图模型及其对应模型之间的关系 例如,如果您在PersonViewModel上更改了Occupation属性,那么该更改将如何深入到PersonModel中的Occupation属性 我现在看到它的唯一方式是在视图模型中公开模型,但我认为这挫败了MVVM的目的——将模型与视图分离C# 维护WPF MVVM视图模型&;模型关系,c#,wpf,mvvm,C#,Wpf,Mvvm,这似乎是一个基本问题,但我无法找出最佳实现。如何管理两个视图模型及其对应模型之间的关系 例如,如果您在PersonViewModel上更改了Occupation属性,那么该更改将如何深入到PersonModel中的Occupation属性 我现在看到它的唯一方式是在视图模型中公开模型,但我认为这挫败了MVVM的目的——将模型与视图分离 internal class PersonViewModel : INotifyPropertyChanged { private readonly Pe
internal class PersonViewModel : INotifyPropertyChanged
{
private readonly PersonModel person;
private OccupationViewModel occupation;
public PersonViewModel(PersonModel person)
{
this.person = person;
}
public OccupationViewModel Occupation
{
get { return this.occupation; }
set
{
if (!this.occupation.Equals(value))
{
this.occupation = value;
this.person.Occupation = this.occupation.Occupation; // Doesn't seem right
this.OnPropertyChanged(new PropertyChangedEventArgs("Occupation"));
}
}
}
}
internal class OccupationViewModel : INotifyPropertyChanged
{
public OccupationViewModel(OccupationModel occupation)
{
this.Occupation = occupation;
}
public OccupationModel Occupation { get; set; } // Is this right?
}
internal class PersonModel
{
public OccupationModel Occupation { get; set; }
}
视图模型正在将模型与视图分离。看起来您可能混淆了视图和视图模型的概念
视图模型既是两者之间的网关又是守门人——它决定了是什么使它从模型到视图,从视图回到模型,以及以什么形式
您可以在VM setter中设置模型属性,也可以不设置。您可以从视图中保存状态,并且仅当用户单击“保存”时才将这些更改传播到模型。您可以在其他位置保留该状态,以便有人可以在将其保留到视图之前返回并进一步处理该状态
internal class PersonViewModel : INotifyPropertyChanged
{
private readonly PersonModel person;
private OccupationViewModel occupation;
public PersonViewModel(PersonModel person)
{
this.person = person;
}
public OccupationViewModel Occupation
{
get { return this.occupation; }
set
{
if (!this.occupation.Equals(value))
{
this.occupation = value;
this.person.Occupation = this.occupation.Occupation; // Doesn't seem right
this.OnPropertyChanged(new PropertyChangedEventArgs("Occupation"));
}
}
}
}
internal class OccupationViewModel : INotifyPropertyChanged
{
public OccupationViewModel(OccupationModel occupation)
{
this.Occupation = occupation;
}
public OccupationModel Occupation { get; set; } // Is this right?
}
internal class PersonModel
{
public OccupationModel Occupation { get; set; }
}
视图模型可以非常了解模型,因此视图根本不必知道它
我不确定我是否理解您关于在视图模型中公开模型的担忧。在示例代码中没有这样做。您已经公开了一个与您在模型中使用的类型相同的对象,但这就像在模型和视图模型中使用
int
表示年龄一样——您没有公开实际的模型对象;您仍然可以控制是否以及何时在模型上设置视图模型中的值。看起来您应该在PersonViewModel上公开“Person”属性,而不是公开Occupation属性。占用财产似乎是不必要的一层
person属性如下所示,Occupation属性可以由类似“viewModel.person.Occupation”的内容引用
public Person Person
{
get
{
return this.person;
}
set
{
if (!this.person.Equals(value))
{
this.person = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("Person"));
}
}
}
为了显示Model和ViewModel之间可能的关系,我首先简化了您的示例,将
职业
的类型更改为字符串
。然后,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
)在视图中不会产生任何效果。还要注意模型中的属性changedevent
是如何通过管道传输到视图的
现在假设职业
不是一个字符串
,而是一个具有自己属性的类,例如:
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可以在如何向视图显示数据方面提供一定的灵活性。以下是两种方法:
选项1直接在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);
}
}
occulationsalary
属性可直接访问occulation
中的Salary
属性。请注意,现在需要如何处理occulation
的PropertyChanged
事件,并且我们必须在occulation\u PropertyChanged
中重命名属性
选项2(推荐)通过职业视图模型
公开职业的属性。如果您需要实现特定于职业的任何业务逻辑,您应该这样做。举个例子,这可能就是您打算做的:
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
完全相同。与您的职业视图模型
版本的重要区别在于,它公开了职业模型
的属性,而不是职业模型
本身。为什么PersonViewModel.Occupation是可写属性?通常它是只读的——毕竟,谁来设置它呢?我正在考虑公开它,以便其他视图模型可以更改它。或者这是某种方法或命令的用武之地?顺便说一句,我是一个WPF、MVVM新手。Patrick我想Joe说的是,视图模型可以在外部修改,而无需设置它(通过访问其属性):personViewModel.Occupation.Occupation=new OccupationModel(“软件工程师”)代码>…此外,用户不会收到您的评论通知,除非(a)您对他们的答案发表评论,(b)他们对问题加了星号/偏好,或者(c)您在开始提问时,至少在他们的部分姓名前加上“@”--比如“@Joe I wasing…”@Jay,在某些情况下您不想直接设置视图模型吗?我认为视图模型有很多属性。在我看来,设置属性(“PersonViewModel.Occupation”)比遍历所有属性并更改它们更容易。你觉得怎么样?谢谢你的解释。我担心在职业视图模型中暴露职业模型。在视图模型中公开模型是错误的做法吗?我的假设是,模型应该由视图模型封装并对其他人隐藏。@在简单、直接的应用程序中,有时直接公开模型是有利的。如果您处理的是复杂性度量,那么是的,最好通过视图模型上的属性传递您想要公开的任何内容。当您处理组合时,作为一个面向对象的原则,更一般地说,这是正确的。