Data Validation

Avalonia offers different data validation options. In this section we will show you how you can validate the Properties of your ViewModel and how you can style the displayed error message.

Validating a property

Avalonia uses DataValidationPlugins to validate the Properties you bound to. Out of the box Avalonia provide these three validation plugins:

DataAnnotations - ValidationPlugin

You can decorate the Properties of your ViewModel with different Validation-Attributes. You can use the build-in ones, use the CustomValidationAttribute or create your own by derive from ValidationAttribute.

Sample: The property EMail is required and must be a valid e-mail-address

[Required]
[EmailAddress]
public string? EMail
{
    get { return _EMail; }
    set { this.RaiseAndSetIfChanged(ref _EMail, value); }
}

INotifyDataErrorInfo - ValidationPlugin

Avalonia also supports validation of classes that implement INotifyDataErrorInfo. Several MVVM-libraries are using this interface for their data validation, for example the Microsoft.Toolkit.Mvvm-package and the ReactiveUI.Validation-package. For usage instructions please visit the documentation of the MVVM-package of your choice.

Some libraries like the Microsoft.Toolkit.Mvvm use DataAnnotiations for their validation. This may result in conflicts with the DataAnnotations - ValidationPlugin. Please see Manage ValidationPlugins how to solve this issue.

Exception - ValidationPlugin

One more option to validate a property is to raise an Exception inside the setter of your property.

Sample: Validate the property EMail using Exceptions

public string? EMail
{
    get { return _EMail; }
    set 
    {
        if (string.IsNullOrEmpty(value))
        {
            throw new ArgumentNullException(nameof(EMail), "This field is required");
        }
        else if (!value.Contains('@'))
        {
            throw new ArgumentException(nameof(EMail), "Not a valid E-Mail-Address");
        }
        else
        { 
            this.RaiseAndSetIfChanged(ref _EMail, value); 
        } 
    }
}

Exceptions inside the getter of your property are not allowed and will result in a crash of your application.

Customize the appearance of the validation message

To display the validation messages, Avalonia has a control called DataValidationErrors. This control is typically placed inside the ControlTemplate of all Controls that supports data validation, like TextBox, Slider and other. You can create your own Style of the DataValidationErrors-control in order to customize the representation of the error messages.

Example Style for DataValidationErrors

<Style Selector="DataValidationErrors">
  <Setter Property="Template">
    <ControlTemplate>
      <DockPanel LastChildFill="True">
        <ContentControl DockPanel.Dock="Right"
                        ContentTemplate="{TemplateBinding ErrorTemplate}"
                        DataContext="{TemplateBinding Owner}"
                        Content="{Binding (DataValidationErrors.Errors)}"
                        IsVisible="{Binding (DataValidationErrors.HasErrors)}"/>
        <ContentPresenter Name="PART_ContentPresenter"
                          Background="{TemplateBinding Background}"
                          BorderBrush="{TemplateBinding BorderBrush}"
                          BorderThickness="{TemplateBinding BorderThickness}"
                          CornerRadius="{TemplateBinding CornerRadius}"
                          ContentTemplate="{TemplateBinding ContentTemplate}"
                          Content="{TemplateBinding Content}"
                          Padding="{TemplateBinding Padding}"/>
      </DockPanel>
    </ControlTemplate>
  </Setter>
  <Setter Property="ErrorTemplate">
    <DataTemplate>
      <Canvas Width="14" Height="14" Margin="4 0 1 0" 
              Background="Transparent">
        <Canvas.Styles>
          <Style Selector="ToolTip">
            <Setter Property="Background" Value="LightRed"/>
            <Setter Property="BorderBrush" Value="Red"/>
          </Style>
        </Canvas.Styles>
        <ToolTip.Tip>
          <ItemsControl Items="{Binding}"/>
        </ToolTip.Tip>
        <Path Data="M14,7 A7,7 0 0,0 0,7 M0,7 A7,7 0 1,0 14,7 M7,3l0,5 M7,9l0,2" 
              Stroke="Red" 
              StrokeThickness="2"/>
      </Canvas>
    </DataTemplate>
  </Setter>
</Style>

Custom validation style

Manage ValidationPlugins

if needed to, you can enable or disable a specific ValidationPlugin in your App. This can be useful if for example your MVVM-framework uses DataAnnotations to validate the property via INotifyDataErrorInfo. In that case you would see the message twice. Use the ExpressionObserver.DataValidators-collection to add or remove a specific ValidationPlugin.

Example: Remove the DataAnnotations validator

public override void OnFrameworkInitializationCompleted()
{
    // Remove the DataAnnotations validator
    ExpressionObserver.DataValidators.RemoveAll(x => x is DataAnnotationsValidationPlugin);
    
    // Continue with normal startup
    if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
    {
        desktop.MainWindow = new MainWindow()
        {
            DataContext = MainWindowViewModel.Instance
        };
    }

    base.OnFrameworkInitializationCompleted();
}

最后更新于