Saturday 1 March 2014

How to display the Validation Error message of the Property inside a binding control - WPF(XAML)

In this article we are going to see how to bind the error message of validation  of a Property to display inside the binded control, For that we have to place a textbox inside a adorned element placeholder and bind the textbox of it to the element name of adorned and path to the AdornedElement.(Valiadtion.Errors)[0].ErrorContent, Here Validation.Errors is array which contains many errors from that we are taking the first error message from the property called ErrorContent .

 <AdornedElementPlaceholder x:Name="adorelement">
                        <TextBlock Text="{Binding ElementName=adorelement,
                          Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"  
                          VerticalAlignment="Center"
                          HorizontalAlignment="Center" Foreground="OrangeRed" FontSize="12">                         </TextBlock>
 </AdornedElementPlaceholder>


Xaml:

<Window x:Class="AdornerSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ControlTemplate x:Key="errorTemplate">
            <DockPanel LastChildFill="True">
                <Border BorderBrush="OrangeRed" BorderThickness="1">
                    <AdornedElementPlaceholder x:Name="adorelement">
                        <TextBlock Text="{Binding ElementName=adorelement,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"  VerticalAlignment="Center"
                                   HorizontalAlignment="Center" Foreground="OrangeRed" FontSize="12"></TextBlock>
                    </AdornedElementPlaceholder>
                </Border>
            </DockPanel>   
        </ControlTemplate>
       
        <Style x:Key="txt" TargetType="TextBlock">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="14" />           
            <Setter Property="FontFamily" Value="Arial" />                
        </Style>
        <Style TargetType="TextBox" x:Key="mantxt">
            <Setter Property="Margin" Value="5"    />
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="Height" Value="50" />
            <Setter Property="Width" Value="250"/>
        </Style>
       
        <Style TargetType="TextBox" x:Key="katxt" BasedOn="{StaticResource mantxt}">
            <Setter Property="Foreground" Value="Green" />
        </Style>
       
        <Style x:Key="acc" TargetType="AccessText">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="20" />
            <Setter Property="FontFamily" Value="Arial" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="2*" />          
        </Grid.ColumnDefinitions>
        <AccessText Grid.Row="0" Style="{StaticResource acc}" >Name</AccessText>
        <TextBox Style="{StaticResource mantxt}" Grid.Column="1" Validation.ErrorTemplate="{StaticResource errorTemplate}">
            <TextBox.Text>
                <Binding Path="Name">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBlock Style="{StaticResource txt}" Grid.Row="1">Designation</TextBlock>
        <TextBox Text="{Binding Designation}"  Style="{StaticResource katxt}" Grid.Row="1" Grid.Column="1"></TextBox>
    </Grid>
</Window>



C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AdornerSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Employee emp = new Employee();

        public MainWindow()
        {
       
            InitializeComponent();
            emp.Designation = "Programmer";
            DataContext = emp;
        }
    }
}




Output:



From this article we can understand how the control bind the error message from the property.

How to create a Control Template for the Validation Error - WPF (XAML)

In this article we are going to see how to create a control template for the validation error, For this first we have to create a Validation error for a property and add the validation rule to the binding of the property with control. Then i will raise a validation error for that data binding and results in the change in the color for that control in the border, now we can change the template for that Validation Error, instead of making a border in red color , we going to see some cool stuff like adding additional things to the control by display the exclamatory symbol along with border red, 

For do this we have to create a control template and bind it with the validtion.ErrorTemplate which will override with the default template.

Control Template


AdornedElement Placeholder which represents the element used in the control template, to specify where the decorated element should be placed.

Now we have to create a DockPanel in which specify that the last element added in the collection can occupy the remaining space, so place the adorned element placeholder as last element and add a Border inside the Adorned Element placeholder which will give the color for the Template control on Error.

Control Template:

<ControlTemplate x:Key="errorTemplate">
            <DockPanel LastChildFill="True">
                <Border BorderBrush="OrangeRed" BorderThickness="1">
                <AdornedElementPlaceholder>                   
                    <Border HorizontalAlignment="Right"  BorderBrush="OrangeRed"  Width="20" Height="20" Margin="5" Background="OrangeRed" CornerRadius="5" DockPanel.Dock="Right">
                        <TextBlock Text="!"  VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="20"></TextBlock>
                    </Border>                   
                </AdornedElementPlaceholder>
                </Border>
            </DockPanel>   
        </ControlTemplate>

        

After created the Template bind it with the Validation.ErrorTemplate


XAML :

<Window x:Class="AdornerSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ControlTemplate x:Key="errorTemplate">
            <DockPanel LastChildFill="True">
                <Border BorderBrush="OrangeRed" BorderThickness="1">
                <AdornedElementPlaceholder>                   
                    <Border HorizontalAlignment="Right"  BorderBrush="OrangeRed"  Width="20" Height="20" Margin="5" Background="OrangeRed" CornerRadius="5" DockPanel.Dock="Right">
                        <TextBlock Text="!"  VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="20"></TextBlock>
                    </Border>                   
                </AdornedElementPlaceholder>
                </Border>
            </DockPanel>   
        </ControlTemplate>
       
        <Style x:Key="txt" TargetType="TextBlock">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="14" />           
            <Setter Property="FontFamily" Value="Arial" />                
        </Style>
        <Style TargetType="TextBox" x:Key="mantxt">
            <Setter Property="Margin" Value="5"    />
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="Height" Value="50" />
            <Setter Property="Width" Value="250"/>
        </Style>
       
        <Style TargetType="TextBox" x:Key="katxt" BasedOn="{StaticResource mantxt}">
            <Setter Property="Foreground" Value="Green" />
        </Style>
       
        <Style x:Key="acc" TargetType="AccessText">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="20" />
            <Setter Property="FontFamily" Value="Arial" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="2*" />          
        </Grid.ColumnDefinitions>
        <AccessText Grid.Row="0" Style="{StaticResource acc}" >Name</AccessText>
        <TextBox Style="{StaticResource mantxt}" Grid.Column="1" Validation.ErrorTemplate="{StaticResource errorTemplate}">
            <TextBox.Text>
                <Binding Path="Name">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBlock Style="{StaticResource txt}" Grid.Row="1">Designation</TextBlock>
        <TextBox Text="{Binding Designation}"  Style="{StaticResource katxt}" Grid.Row="1" Grid.Column="1"></TextBox>
    </Grid>
</Window>



C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AdornerSample
{
    public class Employee
    {

        private string _name;
        public string Name
        {
            set { _name = value;
                if(string.IsNullOrEmpty(value))
                    throw new ApplicationException("Employee Name is Mandatory");
            }
            get { return _name; }
        }

        private int _id;
        public int Id {

            set
            {
                _id = value;
            }
            get {
                return _id;
            }
       
        }

        private string _designation;
        public String Designation
        {
            set { _designation = value; }
            get { return _designation; }
        }

        private int _salary;
        public int Salary {

            set { _salary = value; }
            get { return _salary; }
        }
    }
}



Output:




From this article anyone can easily understand how to create a control template in xaml.