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;

  }

}