In WPF is important to use AdornerDecorator
in xaml. Did you use it?
<AdornerDecorator>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Margin="3" Text="Name: " />
<TextBox Grid.Row="0" Grid.Column="1"
Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="0" Grid.Column="2" Margin="3" MaxWidth="150" TextWrapping="Wrap"
Text="Name not empty, not equal 'foo' and max length is 16" />
<TextBlock Grid.Row="1" Grid.Column="0" Margin="3" Text="Surname: " />
<TextBox Grid.Row="1" Grid.Column="1"
Text="{Binding Surname, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Grid.Column="2" Margin="3" MaxWidth="150" TextWrapping="Wrap"
Text="Surname should be equal 'foo'" />
<TextBlock Grid.Row="2" Grid.Column="0" Margin="3" Text="Phone number: " />
<TextBox Grid.Row="2" Grid.Column="1"
Text="{Binding PhoneNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="2" Grid.Column="2" Margin="3" MaxWidth="150" TextWrapping="Wrap"
Text="Phone number required and allow from 9 to 12 digits" />
</Grid>
</AdornerDecorator>
Also you can use library https://github.com/Karnah/ReactiveValidation which has fluent-interface and build-in MVVM support.
Sample:
public class CarViewModel : ValidatableObject
{
public CarViewModel()
{
Validator = GetValidator();
}
private IObjectValidator GetValidator()
{
var builder = new ValidationBuilder<CarViewModel>();
builder.RuleFor(vm => vm.Make).NotEmpty();
builder.RuleFor(vm => vm.Model).NotEmpty().WithMessage("Please specify a car model");
builder.RuleFor(vm => vm.Mileage).GreaterThan(0).When(model => model.HasMileage);
builder.RuleFor(vm => vm.Vin).Must(BeAValidVin).WithMessage("Please specify a valid VIN");
builder.RuleFor(vm => vm.Description).Length(10, 100);
return builder.Build(this);
}
private bool BeAValidVin(string vin)
{
// Custom vin validating logic goes here.
}
// Properties with realization INotifyPropertyChanged goes here.
}
Here quick start for WPF applications: https://github.com/Karnah/ReactiveValidation/wiki/WPF.-Quick-start