WPF implements verification of TextBox input content

1.ValidatesOnExceptions verification

<Window
    x:Class="WpfApplication.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:local="clr-namespace:WpfApplication"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow"
    Width="400"
    Height="500"
    mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <StackPanel>
        <TextBox Margin="0,10,0,5" Text="{Binding UserName, ValidatesOnExceptions=True}" />
        <TextBox Margin="0,5,0,5" Text="{Binding Age}" />
        <Button Content="Reguster" />
    </StackPanel>
</Window>
using GalaSoft.MvvmLight;
using System;

namespace WpfApplication
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string userName;
        public string UserName
        {
            get
            {
                return userName;
            }
            set
            {
                if (string.IsNullOrWhiteSpace(value) || value.Length < 6 || value.Length > 10)
                {
                    throw new ArgumentException("Username must be within 6-10 lengths");
                }
                userName = value;
                RaisePropertyChanged(nameof(UserName));
            }
        }
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
                RaisePropertyChanged(nameof(Age));
            }
        }
    }
}

2. Inherit ValidationRule

<Window
    x:Class="WpfApplication.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:local="clr-namespace:WpfApplication"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow"
    Width="400"
    Height="500"
    mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <StackPanel>
        <TextBox Margin="0,10,0,5">
            <TextBox.Text>
                <Binding Path="UserName">
                    <Binding.ValidationRules>
                        <local:StringLengthRule MaxLength="10" MinLength="5" />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Margin="0,5,0,5" Text="{Binding Age}" />
        <Button Content="Reguster" />
    </StackPanel>
</Window>
using GalaSoft.MvvmLight;
using System;
using System.Globalization;
using System.Windows.Controls;

namespace WpfApplication
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string userName;
        public string UserName
        {
            get
            {
                return userName;
            }
            set
            {
                userName = value;
                RaisePropertyChanged(nameof(UserName));
            }
        }
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
                RaisePropertyChanged(nameof(Age));
            }
        }
    }
    public class StringLengthRule : ValidationRule
    {
        public int? MinLength { get; set; }
        public int? MaxLength { get; set; }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if (!(value is string))
            {
                return new ValidationResult(false, "Value must be a string");
            }
            string ruleValue = value.ToString();
            if (string.IsNullOrWhiteSpace(ruleValue))
            {
                return new ValidationResult(false, $"Value must be at least {MinLength} characters long");
            }
            if (MinLength != null & amp; & amp; ruleValue.Length < MinLength)
            {
                return new ValidationResult(false, $"Value must be at least {MinLength} characters long");
            }
            if (MaxLength != null & amp; & amp; ruleValue.Length > MaxLength)
            {
                return new ValidationResult(false, $"Value must be at least {MaxLength} characters long");
            }
            return ValidationResult.ValidResult;
        }
    }
}

3. Implement the IDataErrorInfo interface

<Window
    x:Class="WpfApplication.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:local="clr-namespace:WpfApplication"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow"
    Width="400"
    Height="500"
    mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <StackPanel>
        <TextBox Margin="0,10,0,5">
            <TextBox.Text>
                <Binding Path="UserName">
                    <Binding.ValidationRules>
                        <DataErrorValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Margin="0,5,0,5" Text="{Binding Age, ValidatesOnDataErrors=True}" />
        <Button Content="Reguster" />
        <TextBlock Foreground="Red" Text="{Binding Error}" />
    </StackPanel>
</Window>
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Controls;

namespace WpfApplication
{
    public class MainWindowViewModel : ViewModelBase, IDataErrorInfo
    {
        private string userName;
        public string UserName
        {
            get
            {
                return userName;
            }
            set
            {
                userName = value;
                RaisePropertyChanged(nameof(UserName));
                RaisePropertyChanged(nameof(Error));
            }
        }
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
                RaisePropertyChanged(nameof(Age));
                RaisePropertyChanged(nameof(Error));
            }
        }

        public string Error
        {
            get
            {
                var errors = new List<string>
                {
                    this[nameof(UserName)],
                    this[nameof(Age)]
                };
                return string.Join(Environment.NewLine, errors.Where(s => !string.IsNullOrWhiteSpace(s)));
            }
        }
        public string this[string columnName]
        {
            get
            {
                if (columnName == nameof(UserName))
                {
                    if (string.IsNullOrWhiteSpace(UserName))
                    {
                        return "User name is required";
                    }
                    if(UserName.Length<6)
                    {
                        return "User name must be at least 6 characters long";
                    }
                    if (UserName.Length > 10)
                    {
                        return "User name must be at most 10 characters long";
                    }
                }
                else if (columnName == nameof(Age))
                {
                    if (Age < 0)
                    {
                        return "You must be at least 0 years old";
                    }
                    if (Age > 120)
                    {
                        return "You must be at most 120 years old";
                    }
                }
                return string.Empty;
            }
        }
    }
}