WPF数据绑定和验证规则最佳实践

101

我有一个非常简单的WPF应用程序,其中我使用数据绑定来允许编辑一些自定义CLR对象。我现在想在用户单击保存时进行一些输入验证。然而,我阅读过的所有WPF书籍都没有真正专门讨论这个问题。我看到您可以创建自定义ValidationRules,但是我想知道这是否会超出我的需求范围。

因此,我的问题是:是否有一个好的示例应用程序或文章,展示了在WPF中验证用户输入的最佳实践?

6个回答

83

我认为现在更倾向于使用IDataErrorInfo的方式进行数据验证。

在此处阅读更多信息:这里


3
我还发现了Cinch框架(http://cinch.codeplex.com/),它包括WPF+MVVM中最佳实践验证的演示,并使用IDataErrorInfo。 - Mark Heath
3
在.NET 4.5中,您可以使用INotifyErrorInfo,它允许您返回对象而不仅是字符串。 - Peter

24

来自微软的Patterns & Practices文档:

数据验证和错误报告

你的视图模型或模型通常需要执行数据验证,并向视图发出任何数据验证错误信号,以便用户可以采取措施进行更正。

Silverlight和WPF提供了支持,在更改与视图中绑定到控件的单个属性时发生数据验证错误的情况下进行管理。对于一个绑定到控件的单个属性,如果视图模型或模型拒绝一个不良值并抛出异常,则可以在该属性的setter中发出数据验证错误。如果数据绑定上的ValidatesOnExceptions属性为true,则WPF和Silverlight中的数据绑定引擎将处理异常并向用户显示视觉提示,表明存在数据验证错误。

但是,在某些情况下应避免使用此方式使用属性来抛出异常。另一种方法是在视图模型或模型类上实现IDataErrorInfo或INotifyDataErrorInfo接口。这些接口允许您的视图模型或模型对一个或多个属性值进行数据验证,并返回错误信息以便通知视图用户出现了错误。

该文档继续解释了如何实现IDataErrorInfo和INotifyDataErrorInfo接口。


3
起初当我看到“抛出异常”这个建议时,我感到有些担忧。很高兴看到后面跟着“尽可能避免以这种方式使用属性抛出异常”。 - kenwarner
22
需要翻译的内容:it should also be noted that some muppet at microsoft decided not to include INotifyDataErrorInfo in .net4 but Only in silverlight. its a pain..请注意,微软的某些人决定在 .net4 中不包括 INotifyDataErrorInfo,而仅包括在 Silverlight 中。这真是太令人头痛了。 - aL3891
5
@al3891- 这将在.NET 4.5中解决 - http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifydataerrorinfo(v=vs.110).aspx - RichardOD
@aL3891 是否有缺失的 INotifyDataErrorInfo 的任何替代方案? - AgentKnopf

10

个人而言,我使用异常来处理验证。它需要以下步骤:

  1. 在数据绑定表达式中,您需要添加“ValidatesOnException=True”。
  2. 在您要绑定的数据对象中,您需要添加DependencyPropertyChanged处理程序,检查新值是否符合您的条件-如果不符合-您将恢复到对象的旧值(如果需要),并且抛出异常。
  3. 在您用于显示控件中无效值的控件模板中,您可以访问Error集合并显示异常消息。

这里的诀窍是仅绑定到从DependencyObject派生的对象。简单的INotifyPropertyChanged实现无法工作-框架中存在一个错误,防止您访问错误集合。


3

此外,请查看这篇文章。据说微软发布了他们的企业库(v4.0),其中涵盖了验证主题,但神秘地没有包括WPF的验证,因此我要引导您阅读的博客文章解释了作者是如何适应此问题的。希望这可以帮助您!


2

您可能会对 WPF应用程序框架(WAF)BookLibrary 示例应用程序感兴趣。它展示了如何在WPF中使用验证,并在存在验证错误时如何控制保存按钮。


0

如果您的业务类直接被UI使用,最好使用IDataErrorInfo,因为它将逻辑放置在其所有者附近。

如果您的业务类是通过对WCF/XmlWeb服务的引用创建的存根类,则不能/不应使用IDataErrorInfo或抛出Exception以供ExceptionValidationRule使用。而是可以:

  • 使用自定义ValidationRule。
  • 在您的WPF UI项目中定义一个部分类,并实现IDataErrorInfo。

1
我知道这个帖子比较老了,但我希望Alex能够回复。这也是我得出的结论,但问题在于您必须为(例如)“Age”属性编写一些验证代码,以便在ValidationRule中它不能大于100,然后在IDataErrorInfo接口中重复相同的逻辑,这会导致逻辑重复。有没有什么方法可以避免这种情况? - JFTxJ
你将逻辑复制到哪里?在某种服务器验证中吗? 我猜你是在UI中使用IDataErrorInfo进行验证,并在业务对象中复制验证,对吗? 如果是这样的话,在两个方面进行验证是正确的。业务对象不能信任UI,并且必须执行自己的验证(尽管看起来是重复的)。 - Alex Pollan
不,验证逻辑的重复在IDataErrorInfo和Custom Validation Rule中。由于Custom Validation Rule是验证数据在实际更新到绑定对象之前的唯一方式,因此需要在IDataErrorInfo中定义该验证(Age 必须小于100)以返回“按字段”消息,但也必须在Custom Validation Rule中实现。有道理吗? - JFTxJ

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