c# - C# WPF 中的 MVVM 帮助我理解模型和视图模型的关系
问题描述
我试图更好地理解 MVVM 概念,但我正在努力解决模型和视图模型的关系。
我可以这样说:模型不知道视图模型,因为视图模型不知道视图吗?
如果我错了,请纠正我,考虑一个简单的 WPF 应用程序,它显示我们应该拥有的一些字符串:
View: XAML TextBlock bound to string property text1
XAML.CS instantiates ViewModel vModel
ViewModel: has property text1
implements INotifyPropertyChanged notifying View of its changes
instantiates Model mModel
Model: has property string text1
?? implements INotifyPropertyChanged notifying ViewModel of its changes ??
在这里,我对最后一部分感到困惑。如果整个逻辑发生在模型中,例如字符串操作,如何在 ViewModel 中处理来自模型的通知?
ViewModel_PropertyChanged 是否可以通过属性名称访问和更改其属性值?我不是说:
if (e.PropertyName == "text1")
因为如果我们有很多属性,那将是一场噩梦
假设属性在 Model 和 ViewModel 中具有相同的名称,我们可以这样做:
// Model PropertyChanged Handler
private void mainModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyPropertyChanged(e.PropertyName);
}
// ViewModel PropertyChanged Notifier
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
然后 ViewModel 可以持有一个 pass-thought 属性
public string text1
{
get { return mModel.text1; }
set { }
}
但这是正确的吗?如果我们需要从 UI 更改此属性怎么办?:
public string text1
{
get { return mModel.text1; }
set
{
if (mModel.text1 != value)
{
mModel.text1 = value;
NotifyPropertyChanged("text1"); // ??
}
}
}
mModel.text1 = 值;- 这将通知包括 UI 在内的所有人它所做的更改 NotifyPropertyChanged("text1"); // ?? - 这将重复此通知
如果 ViewModel 只持有这个传递属性,那么它有什么需要呢?ViewModel 是否只需要对 Model 属性进行一些不同的理解以在 UI 中显示它们?
抱歉,帖子太长了,希望有人可以帮助我。
解决方案
视图模型的作用是塑造、转换或操作数据。例如,这可能意味着提供更大列表的子集,从嵌套数据实体中展平一些属性或将数字/文本值转换为枚举。视图模型中不应存储视图特定信息(例如 SelectedIndex),视图相关信息应存储在视图后面代码的属性中(您仍然可以绑定到它)。
人们对 MVVM 的解释最大的错误是什么构成了“模型”——这是迈克尔在回答中犯的一个错误。在 MVVM 中,模型是不是视图或视图模型的任何东西。数据类是模型的一部分,但不是模型(与 MVC 或其他模式中的方式不同)。事实上,在 MVVM 中,您不应该将数据类称为“模型”,将它们称为数据实体或业务实体在语义上更正确。如果您遵循 n 层架构,“模型”可以包含多个层。
澄清迈克尔的图表:
| View -> ViewModel ->| BL -> DAL -> Data Entities | | -> "the model" |
我之前的这个答案可能会有所帮助:在 MVVM 设计模式中,模型是否应该包含其他模型?- 它解释了这种方法,并有一个返回 MSDN 文档的参考链接。
推荐阅读
- clojure - 如何安全地编译和隐藏 Clojure 代码?
- sql - 通过电子邮件向销售团队发送订单级别的每月佣金
- r - 使用循环将较大维度矩阵转换为较小维度矩阵
- python - datetime.timestamp 在 pandas 应用和数据框选择中返回不同的值
- c++ - 如何使用循环一次显示所有循环信息?功能问题
- python - 在 django 视图中添加 for 循环
- python - os.fork() 将在哪个 CPU 内核上运行子进程?
- javascript - 当用户使用 JavaScript 单击它时如何重置输入类型 = 数字元素
- oracle - 当某些值为空时比较Oracle中的日期?
- spring - Spring MVC项目中的数据源没有形成Bean