MVVM + WPF - 为具有多个视图的 ViewModel 设计
Posted
技术标签:
【中文标题】MVVM + WPF - 为具有多个视图的 ViewModel 设计【英文标题】:MVVM + WPF - Design for ViewModel that has Multiple Views 【发布时间】:2019-03-11 01:01:33 【问题描述】:我开发在各种信息亭上运行的 .NET/Winforms 应用程序。这些应用程序通常是全屏和触摸控制的。最近想用WPF技术和MVVM设计模式。
这些应用程序的可行设计是我有一个在其上切换屏幕(用户控件)的 MainForm(窗口)。因此,您只有一个“当前”屏幕,其中包含上一个、下一个等按钮(就像一个向导)。
大多数应用程序都有非常相似的逻辑。他们例如。需要从用户(一个屏幕)获取 OrderNumber(PIN,任何文本..),通过卡处理付款(第二个屏幕),... 不同应用程序的区别在于 GUI:图像、字体、颜色、显示器分辨率、按钮位置……
我的想法是编写典型的 ViewModel 并将它们放在公共库中。然后,特定的应用程序将为这些 ViewModel 提供它们的视图。然后,每个 ViewModel 将在整个应用程序生命周期内绑定到一个特定的 View。
例子:
库 Common.dll
包含典型的 ViewModel:ScreenGetTextViewModel、ScreenPayByCardViewModel、... (还包含 ViewModel 的默认视图)应用 1:
引用 Common.dll 包含客户端 1 的视图:ScreenGetTextView、ScreenPayByCardView、...(这些视图绑定到 Common.dll 中的 ViewModel)应用 2:
引用 Common.dll 包含客户端 2 的视图:ScreenGetTextView、ScreenPayByCardView、...(这些视图绑定到 Common.dll 中的 ViewModel)在我看来,MVVM 是实现我的要求的正确方法,因为逻辑和 GUI 分离。
我的问题是如何在 WPF 中制作这个,使用什么,在哪里激发自己。我更喜欢没有 3rd 方 MVVM 工具包的简单解决方案(如果合理且可能的话)。
一些子问题/想法:
如何指定应绑定到特定 ViewModel 的 View?使用一些 ViewLocator?将“View”属性放到 ViewModel 中?
我更喜欢编写不与 WPF 耦合的 Common.dll,因为将来可能会出现 UWP 应用程序(如果可能的话)。
谢谢
【问题讨论】:
是的,这是可能的,而且 MVVM 很容易在没有框架的情况下完成。但是 ViewModel 属于(服务)一个 View,而不是相反。我认为你描述的是一个业务逻辑层,分享起来会更有意义。 【参考方案1】:我只见过每个 ViewModel 的一个视图 - 所以如果有其他方法可以做到这一点,我会很感兴趣。
我会为每个视图使用一个 ViewModel,但每个 ViewModel 都继承自公共 ViewModel。
所以 Common.dll 将包含 ScreenPayByCardView,而应用程序 1 将包含继承自 ScreenPayByCardView 的 App1ScreenPayByCardView。这个 ViewModel 甚至可能不包含它自己的逻辑。
【讨论】:
【参考方案2】:在 MVVM 方案中,您通常在视图的 XAML 代码中将视图模型引用为数据上下文。所以没有问题,你的 viewmodel 类的两个实例被两个不同的视图调用。如果您喜欢松散耦合进行单元测试,那么使用视图定位器是有意义的。
如果您的 common.dll 仅包含视图模型,则不应将其耦合到您的 WPF 视图。否则你违反了 MVVM 模式。
对 MVVM 来说相对较新,并且不得不接受框架的限制,我仍然喜欢 Laurent Bugnion 在 Pluralsight 上的 MVVMLight 课程(您的 MSDN 许可证中可能有 3 个月的免费订阅):https://www.pluralsight.com/courses/mvvm-light-toolkit-fundamentals
我还经常查看 MVVMLight 的代码以了解某些服务实现:https://github.com/lbugnion/mvvmlight/
对于第二个项目,我会立即使用 MVVMLight,因为它是开源的。但对于第一个项目来说,感受痛苦并理解为什么 MVVMLight(和其他框架)会发生某些变化是件好事。
希望有帮助!
【讨论】:
以上是关于MVVM + WPF - 为具有多个视图的 ViewModel 设计的主要内容,如果未能解决你的问题,请参考以下文章