使用MVVM模式(特别是使用MVVM Light),如何实现具有多个基元的模型
本文关键字:MVVM 模型 实现 特别是 模式 Light 何实现 使用 | 更新日期: 2024-10-22 04:35:27
我刚刚开始使用MVVM模式,并已决定为我的Windows Phone应用程序使用MVVM Light工具包。
我的问题是:
我在生成一个视图模型时遇到了问题,该模型将视图正确地绑定到一个属性不仅仅是基元类型的模型上——构建模型和附带的视图模型的有效方法是什么,以便视图通过视图模型绑定到模型,并在模型中的值发生变化时正确更新?
如中所示,如何从视图模型中正确引用模型的值?
这类模型的一个例子是类Foo,它有一个属性b,这是一个基元,另一个属性a是类型Bar的,它有自己的属性——基元或其他。
Foo:
public class Foo : ObservableObject
{
public Foo()
{
a = new Bar();
}
public const string aPropertyName = "a";
private Bar _a;
public Bar a
{
get
{
return _a;
}
set
{
Set(aPropertyName, ref _a, value);
}
}
public const string bPropertyName = "b";
private bool _b;
public bool b
{
get
{
return _b;
}
set
{
Set(bPropertyName, ref _b, value);
}
}
}
条形图:
public class Bar : ObservableObject
{
public const string cPropertyName = "c";
private bool _c;
public bool c
{
get
{
return _c;
}
set
{
Set(cPropertyName, ref _c, value);
}
}
}
编辑:为了澄清,在视图模型中设置属性时,我应该做一些类似的事情吗:
public const string cPropertyName = "c";
public bool c
{
get
{
return model.a.c;
}
set
{
model.a.c = value;
RaisePropertyChanged(cPropertyName);
}
}
还是其他什么?
我认为您要问的问题是嵌套与平面视图模型。根据具体情况,这两种方法都是正确的[尽管我更喜欢嵌套视图模型]。我不能建议你使用什么,但以Foo-Bar为例,用Foo中的属性来包装Bar的属性会更有意义[平面视图模型方法]。所以你创建属性c的做法是正确的。
以下是我对两种方法的看法
嵌套视图模型的优势
- 这就是面向对象的意义所在
- 如果您使用LINQ to SQL或Entities,或者ORM,您可以简单地传递ORM对象,而不必传递所有类型的属性
- 可以传递其他视图,因此可以为局部视图创建单独的模型,如果该视图使用局部视图,则可以将局部视图模型类作为视图模型类的属性传递
平面视图模型的优势
- 让事情变得简单易读
在我们公司开发的最后两个WPF应用程序中,我们使用了MVVM
和Caliburn.Micro
。
对于大多数ViewModels
,我们没有创建Models
,因为您应该创建Model
,不是因为否则您会违反一些OOP规则,而是因为您需要它。什么时候应该创建一个单独的Model
?
在我看来,有两种情况:
-
何时可以在其他应用程序中重用
Model
; -
当
ViewModel
变得复杂,并且您开始意识到,您希望通过分离关注点来简化它。从ViewModel
中提取Model
几乎总是很简单的。
总是为每个ViewModel
创建一个Model
是没有意义的。这样做,当你可以避免并发症时,你会使系统过于复杂。
关于绑定到非基元类型。好吧,将直接通知的支持添加到类型中没有任何问题。
这实际上取决于您对ViewModel的使用。
如果您只需要一个或两个复杂类型的属性(示例中为Bar
),则可以在ViewModel中将其展开。如果您知道总是/大部分需要所有复杂属性,那么为复杂模型创建自己的ViewModel并公开ViewModel而不是模型可能是有意义的。
public class Foo : ObservableObject
{
public BarViewModel A
{
public const string aPropertyName = "a";
private Bar _a;
get
{
return _a;
}
set
{
Set(aPropertyName, ref _a, value);
}
}
}
最后但并非最不重要的是:您的复杂模型需要双向绑定吗?如果没有,您可以为模型实现一个属性。
但请注意绑定未实现INotifyPropertyChanged
的对象可能导致内存泄漏查看此答案