//xaml
<Window x:Class="WpfApp91.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp91"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid TextBlock.FontSize="30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" Margin="6"/>
<TextBox Grid.Column="1">
<TextBox.Text>
<Binding Path="Name" ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:MinCharsRule MinimumChars="3"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="Age:" Grid.Row="1" Margin="6"/>
<TextBox Text="{Binding Age,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,
ValidatesOnExceptions=True,ValidatesOnDataErrors=True}" Grid.Column="1" Grid.Row="1" Margin="6"/>
</Grid>
</Window>
//cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp91
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Person
{
Name = "Fred",
Age = 17
};
}
}
public class Person : INotifyPropertyChanged,IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propName)
{
var handler = PropertyChanged;
if(handler!=null)
{
handler?.Invoke(this,new PropertyChangedEventArgs(propName));
}
}
private int age;
public int Age
{
get
{
return age;
}
set
{
if(value<1)
{
throw new ArgumentException("Age must be a positive integer!");
}
if(value!=age)
{
age = value;
OnPropertyChanged("Age");
}
}
}
private string name;
public string Name
{
get
{
return name;
}
set
{
if (value!=name)
{
name = value;
OnPropertyChanged("Name");
}
}
}
public string Error
{
get
{
return null;
}
}
public string this[string columnName]
{
get
{
switch(name)
{
case "Name":
if(string.IsNullOrWhiteSpace(Name))
{
return "Name cannot be empty!";
}
break;
case "Age":
if(Age<1)
{
return "Age must be a positive integer";
}
break;
}
return null;
}
}
}
class MinCharsRule : ValidationRule
{
public int MinimumChars { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if(value?.ToString()?.Length< MinimumChars)
{
return new ValidationResult(false, "Use at least " + MinimumChars.ToString()
+ " characters");
}
return new ValidationResult(true, null);
}
}
}
![]()