ValidationErrorsHostBehavior

  • 3 minutes to read

ValidationErrorsHostBehavior allows tracking validation errors within a UI container.

Assume the following POCO View Model that implements the IDataErrorInfo interface (the IDataErrorInfo interface implementation is generated automatically based on the defined DataAnnotation attributes).

[POCOViewModel(ImplementIDataErrorInfo=true)]
public class ViewModel {
    [Required]
    public virtual string FirstName { get; set; }
    [Required]
    public virtual string LastName { get; set; }
}

This View Model is assigned to a View that contains two fields (FirstName and LastName) and a button that should be disabled until an end-user fills the fields. To accomplish this task, you can use the ValidationErrorsHostBehavior in the following manner.

<UserControl x:Class="Example.Views.View" ...
    xmlns:ViewModels="clr-namespace:Example.ViewModels"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
    DataContext="{dxmvvm:ViewModelSource Type=ViewModels:ViewModel}">
    <UserControl.Resources>
        <dxmvvm:BooleanNegationConverter x:Key="BooleanNegationConverter"/>
    </UserControl.Resources>
    <dxmvvm:Interaction.Behaviors>
        <dxmvvm:ValidationErrorsHostBehavior x:Name="validationErrorsHostBehavior"/>
    </dxmvvm:Interaction.Behaviors>
    <Grid>
        <StackPanel Orientation="Vertical" ...>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="First Name: " .../>
                <TextBox Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                                NotifyOnValidationError=True, ValidatesOnDataErrors=True}" .../>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Last Name: " .../>
                <TextBox Text="{Binding LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                                NotifyOnValidationError=True, ValidatesOnDataErrors=True}" .../>
            </StackPanel>
            <Button Content="Save" ... IsEnabled="{Binding ElementName=validationErrorsHostBehavior, 
                                                   Path=HasErrors, Converter={StaticResource BooleanNegationConverter}}"/>
        </StackPanel>
    </Grid>
</UserControl>

In the code above, the ValidationErrorsHostBehavior is defined for the root element. That means that the behavior tracks all validation errors within the View. To enable validation error notification, it is necessary to customize the bindings as shown at the example above: set the NotifyOnValidationError and ValidatesOnDataErrors properties to True. To identify whether a validation error occurs, use the ValidationErrorsHostBehavior.HasErrors property. This property is bindable, so you can bind it to any UI element: in our case the Button.IsEnabled property is bound to the HasErrors property with the BooleanNegationConverter.

Example

<UserControl x:Class="Example.View.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModel="clr-namespace:Example.ViewModel"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="600"
    DataContext="{dxmvvm:ViewModelSource Type=ViewModel:MainViewModel}">

    <UserControl.Resources>
        <dxmvvm:BooleanNegationConverter x:Key="BooleanNegationConverter"/>
    </UserControl.Resources>
    <dxmvvm:Interaction.Behaviors>
        <dxmvvm:ValidationErrorsHostBehavior x:Name="validationErrorsHostBehavior"/>
    </dxmvvm:Interaction.Behaviors>
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical" HorizontalAlignment="Center">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="First Name: " VerticalAlignment="Center"/>
                <TextBox Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" Width="120"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Last Name: " VerticalAlignment="Center"/>
                <TextBox Text="{Binding LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" Width="120"/>
            </StackPanel>
            <Button Content="Save" HorizontalAlignment="Center" VerticalAlignment="Center" 
                IsEnabled="{Binding ElementName=validationErrorsHostBehavior, Path=HasErrors, Converter={StaticResource BooleanNegationConverter}}"/>
        </StackPanel>
    </Grid>
</UserControl>