101

I have a very simple WPF application in which I am using data binding to allow editing of some custom CLR objects. I am now wanting to put some input validation in when the user clicks save. However, all the WPF books I have read don't really devote any space to this issue. I see that you can create custom ValidationRules, but I am wondering if this would be overkill for my needs.

So my question is this: is there a good sample application or article somewhere that demonstrates best practice for validating user input in WPF?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Mark Heath
  • 48,273
  • 29
  • 137
  • 194

6 Answers6

83

I think the new preferred way might be to use IDataErrorInfo

Read more here

rudigrobler
  • 17,045
  • 12
  • 60
  • 74
  • 3
    I've also found the Cinch framework (http://cinch.codeplex.com/), which includes a demo of best practices validation in WPF+MVVM, and uses IDataErrorInfo – Mark Heath Sep 04 '09 at 06:37
  • 3
    In .NET 4.5 you can use INotifyErrorInfo which allows you to return objects instead of just strings. – Peter Dec 19 '13 at 08:44
24

From MS's Patterns & Practices documentation:

Data Validation and Error Reporting

Your view model or model will often be required to perform data validation and to signal any data validation errors to the view so that the user can act to correct them.

Silverlight and WPF provide support for managing data validation errors that occur when changing individual properties that are bound to controls in the view. For single properties that are data-bound to a control, the view model or model can signal a data validation error within the property setter by rejecting an incoming bad value and throwing an exception. If the ValidatesOnExceptions property on the data binding is true, the data binding engine in WPF and Silverlight will handle the exception and display a visual cue to the user that there is a data validation error.

However, throwing exceptions with properties in this way should be avoided where possible. An alternative approach is to implement the IDataErrorInfo or INotifyDataErrorInfo interfaces on your view model or model classes. These interfaces allow your view model or model to perform data validation for one or more property values and to return an error message to the view so that the user can be notified of the error.

The documentation goes on to explain how to implement IDataErrorInfo and INotifyDataErrorInfo.

Pat
  • 16,515
  • 15
  • 95
  • 114
  • 3
    i got worried at first when I saw the throw an exception recommendation. glad to see that followed by "throwing exceptions with properties in this way should be avoided where possible" – kenwarner Dec 01 '10 at 17:19
  • 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.. – aL3891 May 09 '11 at 12:09
  • 5
    @al3891- this will be sorted in .NET 4.5- http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifydataerrorinfo(v=vs.110).aspx – RichardOD May 05 '12 at 13:20
  • @aL3891 Is there any alternative for the missing INotifyDataErrorInfo ? – AgentKnopf May 22 '13 at 07:15
10

personaly, i'm using exceptions to handle validation. it requires following steps:

  1. in your data binding expression, you need to add "ValidatesOnException=True"
  2. in you data object you are binding to, you need to add DependencyPropertyChanged handler where you check if new value fulfills your conditions - if not - you restore to the object old value (if you need to) and you throw exception.
  3. in your control template you use for displaying invalid value in the control, you can access Error collection and display exception message.

the trick here, is to bind only to objects which derive from DependencyObject. simple implementation of INotifyPropertyChanged wouldn't work - there is a bug in the framework, which prevents you from accessing error collection.

svick
  • 236,525
  • 50
  • 385
  • 514
Greg
  • 565
  • 1
  • 5
  • 13
3

Also check this article. Supposedly Microsoft released their Enterprise Library (v4.0) from their patterns and practices where they cover the validation subject but god knows why they didn't included validation for WPF, so the blog post I'm directing you to, explains what the author did to adapt it. Hope this helps!

murki
  • 879
  • 12
  • 21
2

You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF). It shows how to use validation in WPF and how to control the Save button when validation errors exists.

jbe
  • 6,976
  • 1
  • 43
  • 34
0

If your business class is directly used by your UI is preferrable to use IDataErrorInfo because it put logic closer to their owner.

If your business class is a stub class created by a reference to an WCF/XmlWeb service then you can not/must not use IDataErrorInfo nor throw Exception for use with ExceptionValidationRule. Instead you can:

  • Use custom ValidationRule.
  • Define a partial class in your WPF UI project and implements IDataErrorInfo.
Alex Pollan
  • 863
  • 5
  • 13
  • 1
    I know this is old, but I'm hoping Alex will be able to respond. This is the conclusion I came to also, but the problem is that you have to write some validation for (for exemple) an "Age" property that could not be bigger then 100 in the ValidationRule, then repeat the same logic in the IDataErrorInfo interface, wich duplicates the logic. Is there any way around that? – JFTxJ Sep 20 '13 at 17:33
  • Where do you duplicate the logic? in some kind of server validation? I guess by your comment that you are validating with IDataErrorInfo in the UI and duplicating the validation in the business object, don't you? If so, then it's correct to validate in both sides. The business objects cannot trust UI's and must perform its own validation (though it seems duplication) – Alex Pollan Oct 04 '13 at 08:19
  • No, the duplication of the validation logic is in the IDataErrorInfo and in the Custom Validation Rule... Since the Custom Validation Rule is the only way to validate the data BEFORE it is actually updated to bound object, that validation (Age must be lower then 100) needs to be defined in the IDataErrorInfo to return a "per-field" message, but must also be implemented in the Custom Validation Rule. Makes sense? – JFTxJ Oct 07 '13 at 16:14