Home > Validation > Using Validation.ErrorTemplate

Using Validation.ErrorTemplate


This was originally published as a thread in the MSDN WPF forum before I started this blog. However, today I revisited the thread and decided to maintain it here, now..

There are a couple of known problems and unknown features with Validation.ErrorTemplate that came up frequently, and I’d like to collect the workarounds for these things in one place. This is how far I got:

Problem: The Content of the ErrorTemplate is not displayed correctly

e.g. the red border doesn’t fit around the control, or parts of the error template are not drawn. The reason is that there may not be enough space around the control to display the error template, so the solution is to make the margin of the control big enough that the error template can be drawn.

Unknown Feature: The DataContext of the ErrorTemplate is the Validation.Errors Collection

Haven’t found this in the documentation, but it means that the easiest way to get at an error message in an error template is to use {Binding Path=/ErrorContent}.

Problem: Have to Change the Style of a Control in Order to Set the Error Message as ToolTip

It seems to be impossible to set the ToolTip of a control using Styles or Triggers in the error template. Usually this is worked around by modifying the Style of the control, as in the example from the WPF SDK. However, this has the disadvantage that one has to change the style of the control in order to accommodate Validation, which might interfere with other uses of the Style. There are better workarounds: most elegant by using a ToolTip on some error indicator that is part of the error template, or, if it must be the control itself, using a custom attached property on the AdornedElementPlaceholder like this:

Public Shared ReadOnly AdornedElementToolTipProperty As DependencyProperty = DependencyProperty.RegisterAttached("AdornedElementToolTip", GetType(Object), GetType(Validation), New PropertyMetadata(Nothing, AddressOf OnAdornedElementToolTipChanged))
Public Shared Function GetAdornedElementToolTip(ByVal d As DependencyObject) As Object
    Return d.GetValue(AdornedElementToolTipProperty)
End Function
Public Shared Sub SetAdornedElementToolTip(ByVal d As DependencyObject, ByVal value As Object)
    d.SetValue(AdornedElementToolTipProperty, value)
End Sub
Private Shared Sub OnAdornedElementToolTipChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    Dim placeholder As AdornedElementPlaceholder = TryCast(d, AdornedElementPlaceholder)
    If placeholder IsNot Nothing Then
        Dim control As Control = TryCast(placeholder.AdornedElement, Control)
        If control IsNot Nothing Then
            control.ToolTip = e.NewValue
        End If
    End If
End Sub

One can bind the error message to this property, and this way the error template works without interfering with the control’s style.

Problem: The Error Template is not Displayed when a Page is Loaded

This is by design, since one could assume that the user doesn’t want to see error messages before he/she made any mistakes, but sometimes one needs this functionality. So, the ValidatesOnTargetUpdated property was introduced on the ValidationRule class; by setting it to true, one sees the validation result immediately.

However, there is one caveat: you must make sure that you set the DataContext after the page is initialized; this would be either in the constructor after the generated comment line that says that initialization code should go there, or in the Loaded event. If you want to set the DataContext in XAML, you find a solution for this problem here (among other things): http://wpfglue.wordpress.com/2009/12/08/navigating-from-object-to-object/

Anyway, I hear this will be fixed in WPF 4.0.

Problem: When Using an Expander, the Error Template Remains Visible even if the Expander is Collapsed

This problem is a known bug, unfortunately as far as I know not yet scheduled for fixing. The workaround (found in the MSDN WPF forum) is binding the Visibility property of the outermost element of the error template to the AdornedElement.IsVisible property of the AdornedElementPlaceholder, using the BooleanToVisibilityConverter that comes with WPF.

Standard Error Template

So, this would be my standard error template:

<ControlTemplate x:Key="errorTemplate">
    <Border BorderBrush="Red" BorderThickness="1">
        <Border.Visibility>
            <Binding ElementName="placeholder" Path="AdornedElement.IsVisible">
                <Binding.Converter>
                    <BooleanToVisibilityConverter/>
                </Binding.Converter>
            </Binding>
        </Border.Visibility>
        <StackPanel>
            <AdornedElementPlaceholder x:Name="placeholder"
             v:Validation.AdornedElementToolTip="{Binding Path=/ErrorContent}"/>
        </StackPanel>
    </Border>
</ControlTemplate>

And this would be how I use it:

<StackPanel>
    <TextBox x:Name="Abox" Margin="3" Validation.ErrorTemplate="{StaticResource errorTemplate}"
      Text="{Binding Path=A, UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True}" />
    <Expander Header="Test" IsExpanded="True" Validation.ErrorTemplate="{x:Null}">
        <Expander.BindingGroup>
            <BindingGroup/>
        </Expander.BindingGroup>
        <TextBox x:Name="Bbox" Margin="3"
         Validation.ErrorTemplate="{StaticResource errorTemplate}"
         Text="{Binding Path=B, UpdateSourceTrigger=PropertyChanged,
          ValidatesOnDataErrors=True}"/>
    </Expander>
</StackPanel>

About these ads
Categories: Validation Tags: , ,
  1. Pappu Kumar
    February 17, 2010 at 05:00

    what is the namespace mapped with v: in the example of standard error template in the problem of Expander.

  2. February 17, 2010 at 08:22

    Hi,

    this would be the namespace where you implemented the AdornedElementToolTip property from the code example above. If you downloaded the code from the downloads page, it would be http://wpfglue.wordpress.com/validation, that’s how I called this namespace in my example.

  3. December 16, 2010 at 12:06

    Nice, great that you put all of this together.

    • December 25, 2010 at 10:51

      Hi,

      thanks, and prettige kerstdagen,

      Hans

  4. Nick Leuchtenberg
    March 18, 2011 at 15:04

    Validation.ErrorTemplate question: What if you are using IDataErrorInfo and not a ValidationRule? There is no “ValidatesOnTargetUpdated.” Also, I had this working in .NET 3.5 – where it would show the error template when the page loaded – by calling UpdateSource() on the BindingExpression – but it now is broken in .NET 4.0.

    • March 18, 2011 at 19:41

      Hi,

      if you are using IDataErrorInfo, you can decide by your implementation of the item(propertyName) method whether the error message is displayed on load: if the method returns a value for any property on an unchanged data object, then that value will trigger the error template. At least in WPF 3.5; I haven’t tried this again in WPF 4.0… I like ValidationRules better for other reasons, therefore I didn’t research this further.

      Greetings,

      Hans

  5. twistur
    July 14, 2011 at 17:47

    Hi Hbarck, this is twistur from MSDN forum. Thanks again for the great insight on how to go about validating. I have one question though. I notice that my validation is triggered even during the load when the user has not done anything yet. Is there a way to prevent this?

    • July 16, 2011 at 09:19

      Hi,

      this depends on how you validate. If you use IDataErrorInfo, make sure that the validation methods don’t return a result unless the user has changed the object. If you are using ValidationRules, make sure ValidatesOnTargetUpdated is false…

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: