能行 发表于 2023-11-17 00:42:11

WPF --- TextBox的输入校验

引言

在WPF应用程序开发中,数据校验是确保用户输入数据的正确性和完整性的重要一环。
之前在做一些参数配置功能时,最是头疼各种参数校验,查阅一些资料后,我总结了数据校验方式有两种:

[*]ValidationRule
[*]IDataErrorInfo
接下来分别介绍这两种校验方式。
ValidationRule

ValidationRule 是一个抽象类,提供了抽象方法 Validate(), 它是WPF中用于数据验证的一种机制,它可以在用户输入数据之前或之后执行自定义的验证逻辑。可以轻松地实现对数据的格式、范围、逻辑等方面的验证,并在验证失败时提供相应的反馈信息。
ValidationRule主要作用域在前端页面上。
基本用法

首先创建一个 ValidationRule,我这里设定了两个属性 MaxVal、MinVal,然后在 Validate() 方法中判断空、判断大于上限或小于下限,然后在符合条件是,返回 ValidationResult,并给出错误提示:
public class IntegerValidationRule : ValidationRule
{
    public int MaxVal { get; set; }
    public int MinVal { get; set; }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
      string text = value as string;

      if (!int.TryParse(text, out int result))
      {
            return new ValidationResult(false, "Text cannot be empty.");
      }

      if (result > MaxVal)
      {
            return new ValidationResult(false, "Value out of upper limit range.");
      }

      if (result < MinVal)
      {
            return new ValidationResult(false, "Value out of lower limit range.");
      }

      return ValidationResult.ValidResult;
    }
}接下来创建有个测试使用的 ViewModel:
public class TestViewModel : INotifyPropertyChanged
{
    private TestViewModel() { }

    public static TestViewModel Instance { get; } = new TestViewModel();

    public event PropertyChangedEventHandler? PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private int testField1;
    /// <summary>
    /// 测试属性1
    /// </summary>
    public int TestField1
    {
      get => testField1;
      set
      {
            testField1 = value;
            OnPropertyChanged(nameof(TestField1));
      }
    }

    private int testField2;
    /// <summary>
    /// 测试属性2
    /// </summary>
    public int TestField2
    {
      get => testField2;
      set
      {
            testField2 = value;
            OnPropertyChanged(nameof(TestField2));
      }
    }
}在测试之前,我们可以先看一下 Binding 的方法列表:

可以看到 ValidationRules 是 Binding 下的集合,这意味着 ValidationRule 是在 Binding 下使用且可以执行多个校验规则。校验时按照顺序依次校验。
接下来我们创建一个WPF应用程序,在界面添加 TextBox,命名为”textbox1“,将文本绑定在 TestViewModel 的 TestField1。
且为Validation.ErrorTemplate 绑定一个模板,这里绑定了一个红色的感叹号。
然后为 TextBox 设置触发器,当 Validation.HasError为 true时,将 ToolTip 绑定校验失败的错误提示。
代码如下:
<Window
    x:
    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:WpfApp4"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="900"
    Height="450"
    mc:Ignorable="d">
    <Window.Resources>
      <ControlTemplate x:Key="ValidationTemplate">
            <DockPanel>
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   <TextBlock
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       Margin="-10,0,0,0"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       VerticalAlignment="Center"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       FontSize="22"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       Foreground="Red"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       Text="!" />

            </DockPanel>
      </ControlTemplate>

      
    </Window.Resources>
    <Grid>
      <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
      </Grid.ColumnDefinitions>
      <StackPanel Grid.Column="0">
            <TextBlock
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   HorizontalAlignment="Center"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   FontSize="18"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   FontWeight="Bold"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   Text="Validation Demo" />
            <TextBox
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   Name="textBox1"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   Height="30"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   Margin="10"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   FontSize="22"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   <TextBox.Text>
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       <Binding Path="TestField1" UpdateSourceTrigger="PropertyChanged">
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>         <Binding.ValidationRules>
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel><StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel><local:IntegerValidationRule
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel><StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>      MaxVal="999"
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel><StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>      MinVal="5" />
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>         </Binding.ValidationRules>
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       </Binding>
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   </TextBox.Text>
            </TextBox>

      </StackPanel>
    </Grid>
</Window>最后在窗体后台绑定 ViewModel:
public MainWindow()
{
    InitializeComponent();
    this.DataContext =TestViewModel.Instance;
}测试


[*]为空时,出现红色叹号,ToolTip 提示 "Text cannot be empty."

[*]小于下限时,出现红色叹号,ToolTip 提示 "Value out of lower limit range."

[*]大于上限时,出现红色叹号,ToolTip 提示 "Value out of upper limit range."

IDataErrorInfo

IDataErrorInfo 是一个接口,Viewmodel 实现接口用于在后台,提供数据验证和错误信息。
IDataErrorInfo 主要作用域为后台 ViewModel
该接口包含两个成员:Error 和 this。这两个成员允许你在数据绑定时提供验证错误信息。
基本用法

接下来,在程序里添加 TextBox,命名为”textbox2“,并添加一个 TextBlock 绑定 Error 展示在界面。
<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>后台 TestViweModel 实现 IDataErrorInfo,依旧是判断上限值和下限值,此处不判断空,是因为后台 TestField2 类型是Int,为空时不会赋值,代码如下:
public class TestViewModel : INotifyPropertyChanged, IDataErrorInfo{    //省略上文已有代码..。      private string error;    public string Error    {      get => error;      set      {            error = value; OnPropertyChanged(nameof(Error));      }    }    public string this    {      get      {            switch (columnName)            {<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   case nameof(TestField2):<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       return CheckTestFild2();<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   default:<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>       return null;            }      }    }    public int MaxVal = 999;    public int MinVal = 5;    private string CheckTestFild2()    {      if (TestField2 > MaxVal)      {            Error = "Value out of upper limit range in viewmodel.";      }      else if (TestField2 < MinVal)      {            Error = "Value out of lower limit rangein viewmodel.";      }      else      {            Error = string.Empty;      }<StackPanel Grid.Column="1">
    <TextBlock
      HorizontalAlignment="Center"
      FontSize="18"
      FontWeight="Bold"
      Text="IDataErrorInfo Demo" />
    <TextBox
      Name="textBox2"
      Margin="10"
      VerticalAlignment="Center"
      FontSize="22"
      Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
   <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>   return Error;    }}测试


[*]小于下限时,出现红色文字提示,ToolTip 提示 "Value out of lower limit range in viewmodel."

[*]大于上限时,出现红色文字提示,ToolTip 提示 "Value out of upper limit range in viewmodel."

小结

以上两种数据校验(IDataErrorInfo、ValidationRule)的方式,均可以实现自定义数据校验,例如对数据的格式、范围、逻辑等方面的验证,并在验证失败时提供相应的反馈信息。
ValidationRule适用于在界面做数据校验,且可以定义多个校验规则。
ValidationRule适用于在ViewModel做数据校验,可以做一些无法在前端页面做的事情,比如出现异常值是还原为默认值。
所以两者既可以单独使用,也可以组合使用,即使使用MVVM模式,依旧能够优雅的做数据校验。

来源:https://www.cnblogs.com/pandefu/archive/2023/11/16/17837358.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: WPF --- TextBox的输入校验