作为ViewModel的职责是“准备”Model的属性以在View中显示,那么从ViewModel中引用基础Model的属性的最佳方法是什么?
目前我能想到两个解决方案:
目前我能想到两个解决方案:
选项1 - 在ViewModel中复制Model的属性(包装器方法)
架构
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model-instance for this ViewModel
private Model M;
public string p1
{
get { return M.p1; }
set
{
M.p1 = value;
// assuming View controls are bound to the ViewModel's properties
RaisePropertyChanged("p1");
}
}
// let's say, I only want to check a Checkbox in the View,
// if the value of p2 exceeds 10.
// Raising the property changed notification would get handled
// in the modifying code instead of the missing setter of this property.
public bool p2
{
get
{
if (M.p2 > 10)
{ return true; }
else
{ return false; }
}
}
// Initialize the Model of the ViewModel instance in its c'tor
public ViewModel()
{ M = new Model(); }
}
绑定
<Textbox Text="{Binding p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding p2, Mode=OneWay}"/>
优点
- 完全控制模型属性在视图上的显示方式,如 p2 所示: 按需将int 转换为bool。
- 与选项2相比,ViewModel 属性的更改可以单独引发,可能会稍微提高性能。
缺点
- 违反 DRY。
- 需要编写/维护更多代码。
- 对模型/ViewModel 进行修改很容易变成 shotgun surgery。
选项二 - 将整个模型视为ViewModel的属性
架构
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model instance for this ViewModel (private field with public property)
private Model _M;
public Model M
{
get { return _M; }
set
{
_M = value;
// Raising the changing notification for the WHOLE Model-instance.
// This should cause ALL bound View-controls to update their values,
// even if only a single property actually got changed
RaisePropertyChanged("M");
}
}
// Initialize the Model of the ViewModel instance in its ctor
public ViewModel()
{ M = new Model(); }
}
绑定
<Textbox Text="{Binding M.p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding M.p2, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}"/>
优点
- 可以节省大量代码。
- 降低复杂性。
- 增强可维护性。
缺点
- 在这种方法中,ViewModel 只是 Models 属性的连续流水加热器,除了对 View 进行一些可能的交互逻辑之外。
- 无法控制 Model 属性在 View 中的显示方式 - 最终导致 ViewModel 的完全不必要以及在 View 中实现转换逻辑。