Validating Data
The following page provides a list of examples that demonstrate how to validate data.
All examples in this topic assume that the grid is bound to the Orders table of the Northwind database, unless stated otherwise.
Providing a cell error style
The following example demonstrates how to provide a new style that will change the foreground color of a cell when its value fails the validation process.
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvs_composers"
Source="{Binding Source={x:Static Application.Current},
Path=Composers}"/>
<Style x:Key="cell_error" TargetType="{x:Type xcdg:DataCell}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</Grid.Resources>
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource cvs_composers}}"
CellErrorStyle="{StaticResource cell_error}">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="Period"
CellEditor="{StaticResource periodEditor}">
<xcdg:Column.CellValidationRules>
<local:PeriodVSCompositionCountCellValidationRule/>
</xcdg:Column.CellValidationRules>
</xcdg:Column>
<xcdg:Column FieldName="CompositionCount">
<xcdg:Column.CellValidationRules>
<local:PeriodVSCompositionCountCellValidationRule />
</xcdg:Column.CellValidationRules>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
Providing binding-level validation
The following example demonstrates how to create a custom ValidationRule and apply it to a column's binding to provide binding-level validation.
The implementation for the YearValidationRule is provided below.
- XAML
- C#
- VB.NET
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvs_composers"
Source="{Binding Source={x:Static Application.Current},
Path=Composers}"/>
</Grid.Resources>
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource cvs_composers}}"
UpdateSourceTrigger="RowEndingEdit">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="BirthYear">
<xcdg:Column.DisplayMemberBindingInfo>
<xcdg:DataGridBindingInfo Path="BirthYear">
<xcdg:DataGridBindingInfo.ValidationRules>
<local:YearValidationRule />
</xcdg:DataGridBindingInfo.ValidationRules>
</xcdg:DataGridBindingInfo>
</xcdg:Column.DisplayMemberBindingInfo>
</xcdg:Column>
<xcdg:Column FieldName="DeathYear">
<xcdg:Column.DisplayMemberBindingInfo>
<xcdg:DataGridBindingInfo Path="DeathYear">
<xcdg:DataGridBindingInfo.ValidationRules>
<local:YearValidationRule />
</xcdg:DataGridBindingInfo.ValidationRules>
</xcdg:DataGridBindingInfo>
</xcdg:Column.DisplayMemberBindingInfo>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
using System;
using System.Windows.Controls;
using System.Globalization;
namespace Xceed.Wpf.Documentation
{
public class YearValidationRule : ValidationRule
{
public override ValidationResult Validate( object value, CultureInfo cultureInfo )
{
int year = ( int )value;
if( year > DateTime.Now.Year )
return new ValidationResult( false, "Chosen year cannot be greater than this year." );
return ValidationResult.ValidResult;
}
}
}
Imports System
Imports System.Windows.Controls
Imports System.Globalization
Namespace Xceed.Wpf.Documentation
Public Class YearValidationRule
Inherits ValidationRule
Public Overrides Function Validate( ByVal value As Object, _
ByVal cultureInfo As CultureInfo ) As ValidationResult
Dim year As Integer = CInt( value )
If year > DateTime.Now.Year Then
Return New ValidationResult( False, "Chosen year cannot be greater than this year." )
End If
Return ValidationResult.ValidResult
End Function
End Class
End Namespace
Providing UI-level validation
The following example demonstrates how to create a custom CellValidationRule and add it to a column's CellValidationRules collection to provide UI-level validation.
The implementation for the PeriodVSCompositionCountCellValidationRule and Person class are provided below.
- XAML
- C#
- VB.NET
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvs_composers"
Source="{Binding Source={x:Static Application.Current},
Path=Composers}"/>
<!--A data provider to bind to the Period enum-->
<ObjectDataProvider x:Key="periods"
MethodName="GetValues"
ObjectType="{x:Type local:Period}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Period"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!--A cell editor that will be used to edit a Period column with a combo box-->
<xcdg:CellEditor x:Key="periodEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<ComboBox BorderThickness="0"
MinHeight="22"
VerticalContentAlignment="Top"
SelectedValuePath="."
ItemsSource="{Binding Source={StaticResource periods}}"
SelectedValue="{xcdg:CellEditorBinding}">
<ComboBox.Resources>
<Style TargetType="Popup">
<Setter Property="TextElement.Foreground"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
</Style>
</ComboBox.Resources>
</ComboBox>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</Grid.Resources>
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource cvs_composers}}"
UpdateSourceTrigger="RowEndingEdit">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="Period"
CellEditor="{StaticResource periodEditor}">
<xcdg:Column.CellValidationRules>
<local:PeriodVSCompositionCountCellValidationRule/>
</xcdg:Column.CellValidationRules>
</xcdg:Column>
<xcdg:Column FieldName="CompositionCount">
<xcdg:Column.CellValidationRules>
<local:PeriodVSCompositionCountCellValidationRule />
</xcdg:Column.CellValidationRules>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
using System;
using Xceed.Wpf.DataGrid.ValidationRules;
using Xceed.Wpf.DataGrid;
using System.Globalization;
using System.Windows.Controls;
namespace Xceed.Wpf.Documentation
{
public class PeriodVSCompositionCountCellValidationRule : CellValidationRule
{
public override ValidationResult Validate( object value, CultureInfo culture,
CellValidationContext context )
{
Row parentRow = context.Cell.ParentRow;
int compositionCount;
Period period;
if( context.Cell.FieldName == "Period" )
{
period = ( Period )value;
compositionCount = ( int )parentRow.Cells[ "CompositionCount" ].Content;
}
else
{
period = ( Period )parentRow.Cells[ "Period" ].Content;
compositionCount = ( int )value;
}
if( ( period == Period.Modern ) && compositionCount > 40 )
return new ValidationResult( false, "Composition count must be less than 50 when the period is set to Modern." );
return ValidationResult.ValidResult;
}
}
}
Imports System
Imports Xceed.Wpf.DataGrid.ValidationRules
Imports Xceed.Wpf.DataGrid
Imports System.Globalization
Imports System.Windows.Controls
Namespace Xceed.Wpf.Documentation
Public Class PeriodVSCompositionCountCellValidationRule
Inherits CellValidationRule
Public Overrides Function Validate( ByVal value As Object, ByVal culture As CultureInfo, _
ByVal context As CellValidationContext ) As ValidationResult
Dim parentRow As Row = context.Cell.ParentRow
Dim compositionCount As Integer
Dim period As Period
If context.Cell.FieldName = "Period" Then
period = CType( value, Period )
compositionCount = CInt( parentRow.Cells( "CompositionCount" ).Content )
Else
period = CType( parentRow.Cells( "Period" ).Content, Period )
compositionCount = CInt( value )
End If
If( ( period = Period.Modern ) And ( compositionCount > 40 ) ) Then
Return New ValidationResult( False, "Composition count must be less than 50 when the period is set to Modern." );
End If
Return ValidationResult.ValidResult
End Function
End Class
End Namespace
Implementation of the Person class
- C#
- VB.NET
using System.ComponentModel;
using System.Windows.Media;
namespace Xceed.Wpf.Documentation
{
public class Person: INotifyPropertyChanged, IDataErrorInfo
{
public Person( int personID, string firstName, string lastName, int age )
{
m_personID = personID;
m_firstName = firstName;
m_lastName = lastName;
m_age = age;
}
public Person()
{
}
public int PersonID
{
get
{
return m_personID;
}
}
public string FirstName
{
get
{
return m_firstName;
}
set
{
if( m_firstName != value )
{
m_firstName = value;
this.OnPropertyChanged( "FirstName" );
}
}
}
public string LastName
{
get
{
return m_lastName;
}
set
{
if( m_lastName != value )
{
m_lastName = value;
this.OnPropertyChanged( "LastName" );
}
}
}
public int Age
{
get
{
return m_age;
}
set
{
if( m_age == value )
return;
m_age = value;
this.OnPropertyChanged( "Age" );
}
}
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( string propertyName )
{
if( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
// IDataErrorInfo implementation
[EditorBrowsable( EditorBrowsableState.Never ) ]
[Browsable( false )]
public string Error
{
get
{
return "IDataErrorInfo Error Message";
}
}
[EditorBrowsable( EditorBrowsableState.Never )]
[Browsable( false )]
public string this[ string propertyName ]
{
get
{
if( propertyName == "Age" )
{
if( m_age < 18 )
return "An employee must be 18 years or older.";
}
return string.Empty;
}
}
private string m_firstName = string.Empty;
private string m_lastName = string.Empty;
private int m_personID;
private int m_age = 18;
}
}
Imports System.ComponentModel
Imports System.Windows.Media
Namespace Xceed.Wpf.Documentation
Public Class Person
Implements INotifyPropertyChanged
Public Sub New( personID As Integer, firstName As String, lastName As String, age As Integer )
m_personID = personID
m_firstName = firstName
m_lastName = lastName
m_age = age
End Sub
public Sub New()
End sub
Public ReadOnly Property PersonID As Integer
Get
Return m_personID
End Get
End Property
Public Property FirstName As String
Get
Return m_firstName
End Get
Set( ByVal value As String )
If m_firstName <> value Then
m_firstName = value
Me.OnPropertyChanged( "FirstName" )
End If
End Set
End Property
Public Property LastName As String
Get
Return m_lastName
End Get
Set( ByVal value As String )
If m_lastName <> value Then
m_lastName = value
Me.OnPropertyChanged( "LastName" )
End If
End Set
End Property
Public Property Age As Integer
Get
Return m_age
End Get
Set( ByVal value As Integer )
If m_age = value Then
Return
End If
m_age = value
Me.OnPropertyChanged( "Age" )
End Set
End Property
' INotifyPropertyChanged implementation
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub OnPropertyChanged( ByVal propertyName As String )
If Not Me.PropertyChanged Is Nothing Then
Me.PropertyChanged( Me, New PropertyChangedEventArgs( propertyName ) )
End If
End Sub
private string m_firstName = string.Empty;
private string m_lastName = string.Empty;
private m_personID As Integer
Private m_age As Integer = 18
End Class
End Namespace