I'm trying to implement validation in my WPF application using the IDataErrorInfo
interface, and I've encountered a not-so-desirable situation.
I have this template which is used when a control fails to validate
<ControlTemplate x:Key="errorTemplate">
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="Right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" Foreground="White" />
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
Everything is well until I try to display something above the control that failed validation, such as displaying a dock item above it:
How can I avoid this and make my error template displayed below the dock item, as it should?
EDIT
I found that I could wrap my TextBox
with an AdornerDecorator
to fix this, but I really don't want to do this for each and every TextBox
control in my application. Is there maybe a way to set it with a Style
or some other way?
EDIT 2
I could probably change the default TextBox
ControlTemplate to include an AdornerDecorator
, but I'm not too keen on changing any of WPF's default control templates. Any other suggestions are welcome.
I would use a style, and here here's an example of one that you can easily adapt.
Note that the ErrorContent is coming from (Validation.Errors).CurrentItem.ErrorContent as opposed to Errors[0]. Although both will work, the latter will litter your output window with swallowed exceptions as outlined here.
OK, I found a relatively simple solution which doesn't force me to change any control templates.
Instead of decorating each
TextBox
with anAdornerDecorator
like thisI can have the
AdornerDecorator
wrap my entire view, which achieves the same result.This way I can define it at most one time per view.
Based on @AdiLester great answer, if your controls are deriving from a base class and you don't want to put
AdornerDecorator
in XAML of each control, then go this way: