Friday, November 29, 2013

Simple Validation in WPF

http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=103359&aid=690130

Introduction

A simple example of validation in xaml for wpf controls and displaying error messages.

Background  

I was looking for something out-of-the-box from WPF where no extra coding of style or template is needed for displaying validation errors, where we just need to code the validation logic for each control and it should automatically display error icon or message next to the control. However I did not find anything straight forward like that in WPF. But in two simple steps it can be achieved.

Using the code  

Here is a very simple form in xaml that is created which has three text box controls.

Let us add code so that when values are entered in the above text boxes, they automatically run validation and if there is validation errors, they will be displayed next to the corresponding control. In order to do this the following two steps are needed.
1. Create a ControlTemplate with AdornedPlaceHolder
2. Implement validation class inheriting abstract class called ValidationRule.

Here is the sample validation control template. Let us start with a very simple validation control template where all we have a text block which will display a red exclamatory sign next to the control that has error.
 <ControlTemplate x:Key="validationErrorTemplate">
            <DockPanel>
                <TextBlock Foreground="Red" DockPanel.Dock="Top">!</TextBlock>
                <AdornedElementPlaceholder x:Name="ErrorAdorner" >
</AdornedElementPlaceholder>
            </DockPanel>
        </ControlTemplate> 

Now let us also create a valiadtor class by inheriting from ValidationRule class and implementing its' abstract method as below.
public class NameValidator : ValidationRule
    {
        public override ValidationResult Validate(object value, 
                        System.Globalization.CultureInfo cultureInfo)
        {
            if (value == null)
                return new ValidationResult(false, "value cannot be empty.");
            else
            {
                if (value.ToString().Length > 3)
                    return new ValidationResult(false, 
                    "Name cannot be more than 3 characters long.");
            }
            return ValidationResult.ValidResult;
        }
    }      
 Let plug this validation control template and the validation rule with control that we want to validate.
 <TextBox Height="23" HorizontalAlignment="Left" Grid.Column="1" Grid.Row="0" 
                 Name="textBox1" VerticalAlignment="Top" Width="120" 
                 Validation.ErrorTemplate="{StaticResource validationErrorTemplate}"
                 >
            <TextBox.Text>
                <Binding Path="Name" Mode="TwoWay" UpdateSourceTrigger="LostFocus">
                    <Binding.ValidationRules>
                        <local:NameValidator></local:NameValidator>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox> 

When we run this now and enter a name longer than three characters long, it displays the red exclamatory sign indicating validation error.
 

Now let us just replace the TextBlock in the above  validation control template code  (the line that is in bold) by StackPanel containing an ellipse and textblock to display the same validation error as below.
<ControlTemplate x:Key="validationErrorTemplate">
            <DockPanel>
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
                <Grid Width="12" Height="12">
                    <Ellipse Width="12" Height="12" Fill="Red" 
                     HorizontalAlignment="Center" VerticalAlignment="Center"
                             
                             ></Ellipse>
                    <TextBlock Foreground="White" FontWeight="Heavy" FontSize="8" 
                               HorizontalAlignment="Center" VerticalAlignment="Center" 
                               TextAlignment="Center" 
                               ToolTip="{Binding ElementName=ErrorAdorner, 
                               Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
                               >X</TextBlock>
                </Grid>
                <TextBlock Foreground="Red" FontWeight="12" Margin="2,0,0,0" 
                           Text="{Binding ElementName=ErrorAdorner, 
                           Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
                           ></TextBlock>                    
                </StackPanel>
                <AdornedElementPlaceholder x:Name="ErrorAdorner" >
                </AdornedElementPlaceholder>
            </DockPanel>
        </ControlTemplate>   

Now when we run the code and validation fails, validation error will be displayed as shown in the screenshot below. (coded validator class for  age and phone number as well)



That is all that is needed for the simplest validation error to show up next to the control. Notice in the validation control template, we are using a DockPanel as the layout control, therefore we can easily change where the error icon and error message will be displayed, we can display them on top of control that is failing validation (as above picture) or on the left, right, bottom.

No comments:

Post a Comment