Friday, May 30, 2014

Prevent System.Windows.Data Error in Output window while evaluating Validation.Errors in XAML


Validation of UI input parameters in WPF is a frequently requirement. There are several approaches to realize an input validation. You can use custom ValidationRule, ExceptionValidationRule or IDataErrorInfo. Excellent descriptions how to use validation in WPF can be found here:
If validation fails, it is desirable to show an error message with a hint in the GUI. In the MSDN library Microsoft shows an example of how to implement this (http://msdn.microsoft.com/en-us/library/system.windows.data.binding.validationrules%28v=vs.110%29.aspx).:
<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
 <Style.Triggers>
  <Trigger Property="Validation.HasError" Value="true">
   <Setter Property="ToolTip"
           Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                           Path=(Validation.Errors)[0].ErrorContent}" />
  </Trigger>
 </Style.Triggers>
</Style>
This works fine, but produces some exceptions in the Output window, if the error is corrected after occurring:
System.Windows.Data Error: 17 :
Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)'
(type 'ReadOnlyObservableCollection`1').
BindingExpression:Path=(0)[0].ErrorContent; DataItem='TextBox'
(Name='Input1'); target element is 'TextBox'
(Name='Input1'); target property is 'ToolTip' (type 'Object')
ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified
argument was out of the range of valid values.
Parameter name: index'
The Attached Property Validation.Errors of the Validation class has no elements, accessing the first element results in an ArgumentOutOfRangeException. System.Collections.ObjectModel.ReadOnlyObservableCollection<ValidationError> is the type of the Validation.Errors Attached Property. This type is in XAML wrapped by CollectionView. Instead of using the index of the ReadOnlyObservableCollection that lead to an exception, if there are no errors, we can use the CurremtItem property of the CollectionView. The property will return nothing if there are no errors, so no exception will be produced:
<Setter Property="ToolTip"
        Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                 Path=(Validation.Errors).CurrentItem.ErrorContent}"/>

5 comments: