tags:

views:

168

answers:

2

I've only scraped the surface of validation in WPF and have come across a scenario that is likely fairly common: I have a TextBox whose value needs to be validated against a variable data type, depending on the context. For example, if the context's data type is 'int,' then the TextBox needs to accept only input that can be converted to an Int32.

My first thought was to inherit from the ValidationRule class and to include the context and to use a switch inside the overridden Validate function, but I am unable to bind anything to it since it is not a FrameworkElement.

Any thoughts?

+1  A: 

You can expose IDataErrorInfo. This lets you do data validation with complex logic.

Reed Copsey
I've only seen a couple of articles that use IDataErrorInfo and they don't do a good job of explaining how to take advantage of its flexibility. Do you have any examples / articles that would apply to my situation?
someweather
Here's a simple sample: http://www.thejoyofcode.com/New_in_WPF_3_5_2_Support_for_IDataErrorInfo.aspx It shows having multiple logical conditions in a single validation, using this interface.
Reed Copsey
I'm afraid this approach isn't going to work in my situation, as I need something more abstract and less connected to the business objects. I guess what I'm looking for is even a workaround that allows me to effectively bind a validation rule to a given textbox depending on its context, or something along those lines...
someweather
Wrap your business objects in a ViewModel, and have the ViewModel implement INotifyPropertyChanged and IDataErrorInfo. This is the approach I take, as it gives you complete control
Reed Copsey
Thank you. Having the ViewModel implement the IDataErrorInfo interface is clever and exactly what I was looking for.
someweather
A: 

Personally I don't like using IDataErrorInfo for something this simple because it requires a gratuitous creation of a ViewModels and a lot of extra code where none should be necessary. It should be as simple as this:

I have a markup extension that allows me to create a binding with custom validation code specfied as a C# expression. This is extremely simple to do, except for the C# parser: Just implement ProvideValue() by constructing a MultiBinding that uses a converter and builds the appropriate validation structure. This allows the validation expression to receive the containing DataContext and the user-specified Binding object in addition to the value being validated.

With this solution coded, you can do something like this:

BoundProperty="{my:ValidatedBinding
  Path=SomeProperty,
  ValidationExpression = context is TextBox ? (int)value>3 : (int)value<7,
  Mode=TwoWay,
  Converter=...

You could easily adapt my solution without the C# parser by creating the expression as a lambda in the code-behind and referencing it with x:Static:

public static reaonly Expression myValidatorExpression =
  (object value, object context, BindingBase binding) =>
    context is TextBox ? (int)value>3 : (int)value<7;

...
  ValidationExpression={x:Static local:MyClass.myValidatorExpression}

In general I find this technique easier and clearer than using ViewModels. I still use ViewModels when there is a complex transformation needed, otherwise just pure XAML straight to the business objects layer.

Note that this approach assumes your business objects layer is not tied to any particular the back-end storage layout (eg SQL table structure). If it were, changing the back-end storage would require changing my UI and this would not be desirable either, so a ViewModel would be desirable from that standpoint. But if not, I always prefer to keep it simple and just use straight XAML.

Ray Burns
Thanks for your response, though I'm not sure I understood all of the implementation details; I'd be interested in seeing more code, assuming it's not proprietary.The prior answer is convenient for my scenario because I am already using the MVVM pattern and have all validation factors inside of the same ViewModel.
someweather