WPF最佳实践:自定义控件是否与MVVM设计兼容?

16

我想创建一个通用控件,它可以在我的页面上重复使用: 一个包含Address1、Address2、City、State、Zip等内容的AddressControl。

最初我只是创建了一个类(AddressEntity),其中包含所有这些项目,并实现了INotifyPropertyChanged。我在AddressControl的Code-Behind中将该类包含为DependencyProperty,并将其用作绑定其属性的DataContext。

然后,有人说我的代码很丑,建议我研究MVVM。看一下,我认为:

  • AddressEntity.cs将只是数据容器(即Address1、Address2等)和成员函数(即Clone、ToString等)
  • 我需要一些AddressViewModel来包装我的AddressEntity,并提供属性变更通知、验证等
  • 我需要某种方式来展示“View”。

问题在于,我看过的所有示例都是将UserControl作为视图,而不是CustomControl。在深入研究之前...

  • 能否在此示例中同时使用MVVM +自定义控件?
  • 与UserControl相比,它是否基本相同(CustomControl vs UserControl),除了主要的差异UserControl vs CustomControl外? 基本上,我的CustomControl真的只是一个View吗?

参考文献:WPF的Model-View-ViewModel (MVVM)设计模式


下面的两个答案似乎相互矛盾。我现在很困惑...特别是第二个答案听起来更有可能,但第一个答案已经有(迄今为止3票)。 - myermian
我同意NVM的观点。我个人也感觉自定义控件和MVVM不能很好地结合在一起。你可以在同一个项目中拥有CC和UC,但是我无法想象为我的CC添加VM,而为UC添加VM则是有意义的。 - akjoshi
1
@akjoshi 我不明白为什么纯WPF和MVVM有任何关系。实际上,无论是自定义控件还是用户控件,您都不需要使用MVVM,我甚至会说在创建用户或自定义控件时不应使用MVVM。但是,如果使用这些控件,那么MVVM是一种很好的使用方式。我认为很容易区分“现在我正在制作业务逻辑并使用MVVM”和“现在我正在创建一个控件,从未听说过mvvm”。例如,我们构建了一个完整的图形控件,其中包括节点连接等所有自定义控件,但是大多数情况下使用此控件是通过视图模型完成的。 - dowhilefor
2
@dowhilefor 是的,这一点始终存在,使用MVVM并非必要。您自己提供了MVVM不适用于CC的提示 - “业务逻辑”;通常,CC没有任何业务逻辑,只有控件的实现和模板,CC应该可用于多个应用程序(例如您的图表控件)。客户端应用程序使用MVVM CC是有意义的,但不适用于创建 CC。 - akjoshi
1
@akjoshi 好的,那我们意见一致,我只是误解了你。 - dowhilefor
2个回答

23

CustomControls 永远不会使用 mvvm 进行开发。

你需要的是可复用数据视图而不是控件(Custom Control)。

UserControls 和 CustomControls 是两个完全不同的东西。

编辑:

尽管 UserControls 最初的目的是什么,但在 MVVM 中,当你需要一个与你的模型/视图模型特定匹配的可重用视图时,你会使用 UserControl。除了自动生成的 InitializeComponent 部分之外,它就是 XAML 代码,没有任何的后台代码。通常情况下,你将 UserControl 保存在和使用它的项目中相同的项目中。

如果你需要一个通用的功能块并且该功能块需要一个视图,并且该功能块有潜在的在当前应用程序范围之外使用的可能性,那么你应该选择 CustomControl。在这种情况下,控件实际上是在一个代码文件中定义的,控件的外观(可以覆盖)通过 XAML 在资源字典中传递。通常情况下,你将 CustomControl 保存在单独的 ControlLibrary 项目中,并在你希望使用它的项目中引用库。

尊重 WallStreetProgrammer 的意见,仅根据是否需要无样式控件来选择 UserControl 和 CustomControl 是有点天真的。


不幸的是,当涉及到用户控件与自定义控件时,还有一些额外的问题需要考虑。例如,如果处理ResourceDictionaries出现问题,可能会使Usercontrols几乎无用。但我同意,选择使用用户控件或自定义控件不应仅仅基于缺乏样式。 - dowhilefor
如果资源字典没有正确处理,甚至可能会使整个应用程序无法使用 :p。但这与问题有什么关系呢? - NVM
当然,你是正确的,但在用户控件xaml中使用MergedDictionary比在存储自定义控件样式的xaml(或generic.xaml)中使用MergedDictionary要糟糕得多。我通过艰难的经历学到了这个教训。老实说,我根本看不出使用用户控件有任何意义,但这只是我的个人观点。 - dowhilefor
通常情况下,您会将CustomControl保存在单独的ControlLibrary项目中,并在希望使用它的项目中引用该库。但是这个说法并不完全准确,因为如果您尝试在Blend中创建WpfControlLibrary,它默认会创建一个UserControl。 - usefulBee
那么...在使用UserControl时,使用MVVM是好的选择,而在使用自定义控件时则不是? - Konrad

3
当使用MVVM时,Model和ViewModel不应该依赖于View,也就是说它们不应该关心使用它们的视图类型。
在WPF中,自定义控件和用户控件的区别在于自定义控件是无样式的,并且可以通过其ControlTemplate进行自定义。如果您正在编写一个通用的控件库(就像Microsoft一样),那么这就是您应该编写的内容。但是,如果您对控件有特定的外观想法,请使用用户控件,它的速度更快,但只有一个外观,即您为其定义的外观。
在MVVM项目中,常见的做法是混合使用自定义控件和用户控件。例如,您可能会使用来自Microsoft的一堆自定义控件(如文本框和文本块)并将它们组合成用户控件。
请参见 Control Authoring Overview

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接