Introduction
In this article, we will see how validation can be done in WPF and also how the error can be displayed.
There are 3 ways in which the validation can be done in WPF.
- By using Exception validation
- By using IDataErrorInfo
- By using ValidationRules
Using the Code
The example is very simple, we will add validation to the name property such that the characters of name is >6 and <10.
The View
So we will start implementing error validation by using each of the ways defined earlier.
By Using Exception Validation
In this way of validation, it is important that we specify ValidatesOnExceptions=True
on the binding. Here, the framework will check for any exception thrown when the setter of the associated binding property is called. The framework will catch the exception ArgumentException
and marks the field with error state.
The View
<TextBox Text="{Binding StudentName,
ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
FontSize="20"/>
The Code behind View
namespace TestWpfValidation
{
public partial class MainWindow : Window
{
private string _studentName;
public string StudentName
{
get { return _studentName; }
set
{
if (value.Length < 6 || value.Length > 50)
{
throw new ArgumentException("Name should be between range 6-50");
}
_studentName = value;
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
}
}
Output
So after running this application you observe that the textbox validates itself, but it does not display error message in a beautiful manner. We will tackle how to display the error message at the end using styles.
Key Notes to Implement
- In the setter, the binded property setter needs to throw
ArgumentException
with error message as parameter to this exception.
- In View, make
ValidatesOnExceptions=True
on the property.
By Using IDataErrorInfo
The View
TextBox Text="{Binding StudentName,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
VerticalAlignment="Center"
FontSize="20"/>
The ViewModel
public partial class MainWindow : Window, IDataErrorInfo, INotifyPropertyChanged
{
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public string StudentName
{
get { return _studentName; }
set
{
_studentName = value;
OnPropertyChanged("StudentName");
}
}
public string this[string columnName]
{
get
{
string result = String.Empty;
if (columnName == "StudentName")
{
if (StudentName.Length < 6 || StudentName.Length > 10)
{
result = "Name should be between range 3-50";
}
}
return result;
}
}
public string Error
{
get
{
return string.Empty;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private string _studentName;
}
The Error
property on IDataErrorInfo
represents the error on the MainWindow
. Hence, we are just returning string.empty
as we are not validating MainWindow
.
Key Notes to Implement
- In
View
, make ValidatesOnDataErrors =True
on the property.
- For the
ViewModel
, implement two interfaces IDataErrorInfo
, INotifyPropertyChanged
.
By Using ValidationRules
Create a Validation Rule by inheriting ValidationRule
class and implement the validation logic.
public class StudentNameValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string valueToValidate = value as string;
if (valueToValidate.Length < 6 || valueToValidate.Length > 10)
{
return new ValidationResult(false, "Name should be between range 3-50");
}
return new ValidationResult(true, null);
}
}
In XAML, define the Validation rule on the control that we created on the binding.
<TextBox VerticalAlignment="Center" FontSize="20">
<TextBox.Text>
<Binding Path="StudentName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StudentNameValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<TextBox>
Key Notes to Implement
- Create a new class that implements
- Provide the Validation rule that we created to the
ValidationRules
property in XAML.
Adding Style to the Error
This can be used with all the validations that are defined above.
Also, we can customize the way in which the error should be displayed. This can be done using the controlTemplate
with AdornedElementPlaceHolder
.
<Style x:Key="GeneralErrorStyle">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Right"
Foreground="Red"
FontSize="12pt"
Text="Error"
ToolTip="{Binding ElementName=placeholder,
Path= AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
<AdornedElementPlaceholder x:Name="placeholder" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And then, this style can be applied on the control in XAML.
<TextBox Style="{StaticResource GeneralErrorStyle}"
Text="{Binding StudentName,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}"
HorizontalAlignment="Left"
Width="300"/>
This is how the error is displayed after applying this style: