MVVM 视图模型和属性类型 (PresentationCore.dll )
本文关键字:PresentationCore dll 类型 属性 视图 模型 MVVM | 更新日期: 2023-09-27 18:32:22
我们可以在我的 ViewModel 中使用面向 UI/UI 框架的程序集中的类吗?
今天我讨论了一个问题,其中一个人非常坚持PresentationCore.dll的类不能在ViewModel中使用。(好像他从来没有用过ICommand)但这是对的吗?
根据我的理解,MVVM 只是一种用于解耦视图和视图模型的模式?它没有说明我可以在 ViewModel 中使用什么类型的类,只要它们不创建视图(ViewModel 没有直接引用视图或任何关于视图的特定实现或类型的知识)。
请不要回答什么是好的做法,我只是想弄清楚 MVVM。
有时 MVVM 看起来像有自己的趋势的宗教。 :)
以下是MVVM教派成员之间的圣战主题:
- 先查看与先查看模型;
- 从视图模型中公开/不公开
PresentationFramework
/WindowsBase
类型; - 通过视图模型公开/不公开模型,并将视图直接绑定到模型;
- 转换器与视图模型属性;
- 在视图模型中聚合模型/将模型数据映射到视图模型; 使用
- 事件聚合器/使用服务。
最危险的是"纯粹的MVVM"狂热分子。没有人确切知道什么是"纯MVVM",但如果你违反了他们的信仰,他们准备烧死你。
MVVM 只希望您将视图逻辑与视图模型逻辑分开保存。
仅此而已。
上面的列表只是一组方法,而不是教条。而且,实际上,它们都适合MVVM。使用或不使用只是方便和当前项目架构的问题。
请浏览以下链接:
MVVM 模式
MVVM 基础知识
属性类型没有此类限制。此模式仅通过使用视图模型层解耦视图和模型。
上一个问题/答案中的简单示例:SolidColorBrush
.
此类型在两个不同的程序集中声明:Windows.Foundation.UniversalApiContract (UWP 应用程序) 和 PresencationCore.dll (WPF)。它们都是不同的类型,具有不同的命名空间和不同的标识(类型的标识与其程序集耦合。
程序集 A TypeA
不同于程序集 B 的类型 A。不能将AssemblyA.TypeA
传递给需要AssemblyB.TypeA
的对象
为什么重要?
以该视图模型为例
// WPF namespace
using System.Windows.Media;
public class ExampleViewModel : ViewModelBase
{
public SolidColorBrush Color { get; set; }
}
当您在 WPF 中使用它时,一切都很好并且可以正常工作。现在你想要制作一个 UWP 应用,这将不起作用。UWP 不知道 PresentationCore .dll 的System.Windows.Media.SolidColorBrush
。它只知道Windows.Foundation.UniversalApiContract.dll的Windows.UI.Xaml.Media.SolidColorBrush
,即使它们具有相同的方法,相同的参数甚至相同的实现,它们也是不同的。
更糟糕的是,由于您的ViewModel需要PresentationCore.dll,因此它必须绑定到.NET 3.x或4.x,而UWP基于WinRT/Core Framework。
这是一个紧密的耦合。现在假设你还想使用Xamarin(基于mono的跨平台.NET框架),并且SolidColorBrush
在即Xamarin.Forms中.dll(我没有使用过Xamarin,我不确定它甚至没有这样的名称)。
Linux/Mono版本怎么样?单声道上没有 WPF。控制台应用程序?他们甚至不使用 UI 元素。
然后你不能绑定它,你最终会复制你的视图模型并复制你的表示逻辑等。
使用"MVVM"方法,您提高了可测试性,但尚未存档可重用性和解耦。
没有规范告诉你:"必须这样做。MVVM没有规范,它是一种(架构)模式。
为了上述示例,如果您需要确定颜色,请使用非 ui 特定类型(string
、Color
或您自己的颜色类/结构实现)。
对于视图,您实现了一个"IValueConverter"(例如,请参阅此答案)。
现在,您拥有了漂亮的解耦代码,您可以重用这些代码,并且每个UI平台都可以以自己的方式处理颜色。
这就像以几行代码为代价直接返回SolidColorBrush
一样简单。最重要的是,您可以在任何地方和您创建的每个应用程序中重用ColorToSolidColorBrushValueConverter
。 ColorToSolidColorBrushValueConverter
不依赖于您的特定应用程序,您的应用程序/视图模型也不依赖于它。
写出好的代码并不难,你只需要尝试一下;)