On MSDN Magazine it has a good article about MVVM and they are binding the validation error in the Xaml to Validation.ErrorTemplate="{x:Null}"
. I do not get it why and how they can display from the IDataErrorInfo the error? Anyone can light me on how to get the error message displayed to the screen with the MVVM approach?
When you bind to an object that supports IDataErrorInfo, there are several features of the WPF Binding class to consider:
ValidatesOnDataErrors must be True. This instructs WPF to look for and use the IDataError interface on the underlying object.
The attached property Validation.HasError will be set to true on the target object if the source object's IDataError interface reported a validation problem. You can then use this property with trigger to change the tooltip of the control to display the validation error message (I'm doing this in my current project and the end user's love it).
The Validation.Errors attached property will contain an enumeration of any ValidationResult errors resulting from the last validation attempt. If you're going with the tooltip approach, use an IValueConverter to retrieve only the first item... otherwise you run into binding errors for displaying the error message itself.
The binding class exposes NotifyOnValidationError, which when True, will cause routed events to bubble up from the bound control every time a validation rule's state changes. This is useful if you want to implement an event handler in the container of the bound controls, and then add and remove the validation messages to/from a listbox.
There are samples on MSDN for doing both style of feedback (the tooltips as well as the listbox), but I'll paste below the code I roled to implement the tooltip feedback on my DataGridCells and TextBoxes...
The DataGridCell style:
<Style TargetType="{x:Type dg:DataGridCell}"
x:Key="DataGridCellStyle">
<Setter Property="ToolTip"
Value="{Binding Path=Column.(ToolTipService.ToolTip),RelativeSource={RelativeSource Self}}" />
<Style.Triggers>
<Trigger Property="Validation.HasError"
Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors), Converter={StaticResource ErrorContentConverter}}" />
</Trigger>
</Style.Triggers>
</Style>
The TextBox style:
<Style x:Key="ValidatableTextBoxStyle" TargetType="TextBox">
<!--When the control is not in error, set the tooltip to match the AutomationProperties.HelpText attached property-->
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Mode=Self},Path=(AutomationProperties.HelpText)}" />
<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>
The ErrorContentConverter (for retrieving the first validation error message for the tooltip):
Imports System.Collections.ObjectModel
Namespace Converters
<ValueConversion(GetType(ReadOnlyObservableCollection(Of ValidationError)), GetType(String))> _
Public Class ErrorContentConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
Dim errors As ReadOnlyObservableCollection(Of ValidationError) = TryCast(value, ReadOnlyObservableCollection(Of ValidationError))
If errors IsNot Nothing Then
If errors.Count > 0 Then
Return errors(0).ErrorContent
End If
End If
Return String.Empty
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
End Class
End Namespace
...and finally an example of using the style in a textbox:
<TextBox Text="{Binding Path=EstimatedUnits,ValidatesOnDataErrors=True,NotifyOnValidationError=True}"
Style="{StaticResource ValidatableTextBoxStyle}"
AutomationProperties.HelpText="The number of units which are likely to sell in 1 year." />
I was looking at the same sample just a few minutes ago. Your guess is righ. In this code sample they removed default ErrorTemplate from TextBox control so it would't show red rectangle. Instead of using ErrorTemplate they create ContentProvider with content bound to validation error of specific text box.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With