Using the control templates provided by the Silverlight toolkit I just noticed that those style do not support the validation states for displaying validation errors.

Since you have access to the templates adding them is a quite easy - but boring - job. First of we need to open the template of the standard controls and extract the pieces related to data validation display, then we can modify the provided templates inserting these pieces of code back. We can do this so easily because of the nice way the controls skins work in Silverlight and WPF (there are plenty of resources over the net on this subject so I will not dig into that) and thanks to the Visual State Manager that handles the display state changes without any logic to be added to the control, this link from Jesse Liberty gives a clear picture of the thing: Quick overview of Silverlight validation.

In short to modify the - let’s say - the Textbox template you just have to:

  • Look for the VisualStateManage.VisualStateGroups section of the template and add a VisualStateGroup with the following states in it: Valid, InvalidUnfocused, InvalidFocused. All the data validation framewrok relies on the presence of these 3 states do change the appearance of the control:
    <VisualStateGroup x:Name="ValidationStates">
       <VisualState x:Name="Valid"/>
       <VisualState x:Name="InvalidUnfocused">
          <Storyboard>
             <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                <DiscreteObjectKeyFrame KeyTime="0">
                   <DiscreteObjectKeyFrame.Value>
                      <Visibility>Visible</Visibility>
                   </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
             </ObjectAnimationUsingKeyFrames>
          </Storyboard>
       </VisualState>
       <VisualState x:Name="InvalidFocused">
          <Storyboard>
             <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                <DiscreteObjectKeyFrame KeyTime="0">
                   <DiscreteObjectKeyFrame.Value>
                      <Visibility>Visible</Visibility>
                   </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
             </ObjectAnimationUsingKeyFrames>
             <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen">
                <DiscreteObjectKeyFrame KeyTime="0">
                   <DiscreteObjectKeyFrame.Value>
                      <System:Boolean>True</System:Boolean>
                   </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
             </ObjectAnimationUsingKeyFrames>
          </Storyboard>
       </VisualState>
    </VisualStateGroup>
  • These states operate on some framework elements (validationErrorElement and validationErrorToolTip) so we have to add those too, so at the end of the control template - just before the closing </Grid> tag - add the following piece of code:
    <Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1">
       <ToolTipService.ToolTip>
          <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
             <ToolTip.Triggers>
                <EventTrigger RoutedEvent="Canvas.Loaded">
                   <BeginStoryboard>
                      <Storyboard>
                         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
                            <DiscreteObjectKeyFrame KeyTime="0">
                               <DiscreteObjectKeyFrame.Value>
                                  <System:Boolean>true</System:Boolean>
                               </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                         </ObjectAnimationUsingKeyFrames>
                      </Storyboard>
                   </BeginStoryboard>
                </EventTrigger>
             </ToolTip.Triggers>
          </ToolTip>
       </ToolTipService.ToolTip>
       <Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent">
          <Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z"/>
          <Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8"/>
       </Grid>
    </Border>

You must add this after all the other framework element to be sure that when enabled those controls are displayed over any other element that form the template.

This way you have standard way to display the validation error messages in your templated control. Actually you can use these pieces of codes in you own controls to give them the same look and feel. Also rewriting these pieces of code and applying them to the controls you can totally change the way validation error messages are shown.

Related Content