Xceed DataGrid for WPF v7.3 Documentation
Welcome to Xceed DataGrid, Editors, and 3D Views for WPF v7.3 / Xceed DataGrid for WPF / Code Snippets / Validating Data

In This Topic
    Validating Data
    In This Topic

    The following page provides a list of examples that demonstrate how to validate data. For more data validation-related information, refer to the Validating Data topic.

    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.

    XAML
    Copy Code
    <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
    Copy Code
    <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>

    Implementation of the YearValidationRule validation rule.

    VB.NET
    Copy Code
    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
    C#
    Copy Code
    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;
       }
     }
    }

    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
    Copy Code
    <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>

    Implementation of the PeriodVSCompositionCountCellValidationRule validation rule.

    VB.NET
    Copy Code
    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
    C#
    Copy Code
    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;
       }
     }
    }

    Implementation of the Person class

    VB.NET
    Copy Code
    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
    C#
    Copy Code
    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;
      }
    }