翼度科技»论坛 编程开发 .net 查看内容

WPF --- TextBox的输入校验

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
引言

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

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

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

首先创建一个 ValidationRule,我这里设定了两个属性 MaxVal、MinVal,然后在 Validate() 方法中判断空、判断大于上限或小于下限,然后在符合条件是,返回 ValidationResult,并给出错误提示:
  1. public class IntegerValidationRule : ValidationRule
  2. {
  3.     public int MaxVal { get; set; }
  4.     public int MinVal { get; set; }
  5.     public override ValidationResult Validate(object value, CultureInfo cultureInfo)
  6.     {
  7.         string text = value as string;
  8.         if (!int.TryParse(text, out int result))
  9.         {
  10.             return new ValidationResult(false, "Text cannot be empty.");
  11.         }
  12.         if (result > MaxVal)
  13.         {
  14.             return new ValidationResult(false, "Value out of upper limit range.");
  15.         }
  16.         if (result < MinVal)
  17.         {
  18.             return new ValidationResult(false, "Value out of lower limit range.");
  19.         }
  20.         return ValidationResult.ValidResult;
  21.     }
  22. }
复制代码
接下来创建有个测试使用的 ViewModel:
  1. public class TestViewModel : INotifyPropertyChanged
  2. {
  3.     private TestViewModel() { }
  4.     public static TestViewModel Instance { get; } = new TestViewModel();
  5.     public event PropertyChangedEventHandler? PropertyChanged;
  6.     protected void OnPropertyChanged(string propertyName)
  7.     {
  8.         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  9.     }
  10.     private int testField1;
  11.     /// <summary>
  12.     /// 测试属性1
  13.     /// </summary>
  14.     public int TestField1
  15.     {
  16.         get => testField1;
  17.         set
  18.         {
  19.             testField1 = value;
  20.             OnPropertyChanged(nameof(TestField1));
  21.         }
  22.     }
  23.     private int testField2;
  24.     /// <summary>
  25.     /// 测试属性2
  26.     /// </summary>
  27.     public int TestField2
  28.     {
  29.         get => testField2;
  30.         set
  31.         {
  32.             testField2 = value;
  33.             OnPropertyChanged(nameof(TestField2));
  34.         }
  35.     }
  36. }
复制代码
在测试之前,我们可以先看一下 Binding 的方法列表:

可以看到 ValidationRules 是 Binding 下的集合,这意味着 ValidationRule 是在 Binding 下使用且可以执行多个校验规则。校验时按照顺序依次校验。
接下来我们创建一个WPF应用程序,在界面添加 TextBox,命名为”textbox1“,将文本绑定在 TestViewModel 的 TestField1。
且为Validation.ErrorTemplate 绑定一个模板,这里绑定了一个红色的感叹号。
然后为 TextBox 设置触发器,当 Validation.HasError为 true时,将 ToolTip 绑定校验失败的错误提示。
代码如下:
  1. <Window
  2.     x:
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.     xmlns:local="clr-namespace:WpfApp4"
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  8.     Title="MainWindow"
  9.     Width="900"
  10.     Height="450"
  11.     mc:Ignorable="d">
  12.     <Window.Resources>
  13.         <ControlTemplate x:Key="ValidationTemplate">
  14.             <DockPanel>
  15. <StackPanel Grid.Column="1">
  16.     <TextBlock
  17.         HorizontalAlignment="Center"
  18.         FontSize="18"
  19.         FontWeight="Bold"
  20.         Text="IDataErrorInfo Demo" />
  21.     <TextBox
  22.         Name="textBox2"
  23.         Margin="10"
  24.         VerticalAlignment="Center"
  25.         FontSize="22"
  26.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  27.      <TextBlock
  28.          HorizontalAlignment="Center"
  29.          FontSize="18"
  30.          FontWeight="Bold"
  31.          Foreground="Red"
  32.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  33. </StackPanel>   <TextBlock
  34. <StackPanel Grid.Column="1">
  35.     <TextBlock
  36.         HorizontalAlignment="Center"
  37.         FontSize="18"
  38.         FontWeight="Bold"
  39.         Text="IDataErrorInfo Demo" />
  40.     <TextBox
  41.         Name="textBox2"
  42.         Margin="10"
  43.         VerticalAlignment="Center"
  44.         FontSize="22"
  45.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  46.      <TextBlock
  47.          HorizontalAlignment="Center"
  48.          FontSize="18"
  49.          FontWeight="Bold"
  50.          Foreground="Red"
  51.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  52. </StackPanel>       Margin="-10,0,0,0"
  53. <StackPanel Grid.Column="1">
  54.     <TextBlock
  55.         HorizontalAlignment="Center"
  56.         FontSize="18"
  57.         FontWeight="Bold"
  58.         Text="IDataErrorInfo Demo" />
  59.     <TextBox
  60.         Name="textBox2"
  61.         Margin="10"
  62.         VerticalAlignment="Center"
  63.         FontSize="22"
  64.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  65.      <TextBlock
  66.          HorizontalAlignment="Center"
  67.          FontSize="18"
  68.          FontWeight="Bold"
  69.          Foreground="Red"
  70.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  71. </StackPanel>       VerticalAlignment="Center"
  72. <StackPanel Grid.Column="1">
  73.     <TextBlock
  74.         HorizontalAlignment="Center"
  75.         FontSize="18"
  76.         FontWeight="Bold"
  77.         Text="IDataErrorInfo Demo" />
  78.     <TextBox
  79.         Name="textBox2"
  80.         Margin="10"
  81.         VerticalAlignment="Center"
  82.         FontSize="22"
  83.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  84.      <TextBlock
  85.          HorizontalAlignment="Center"
  86.          FontSize="18"
  87.          FontWeight="Bold"
  88.          Foreground="Red"
  89.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  90. </StackPanel>       FontSize="22"
  91. <StackPanel Grid.Column="1">
  92.     <TextBlock
  93.         HorizontalAlignment="Center"
  94.         FontSize="18"
  95.         FontWeight="Bold"
  96.         Text="IDataErrorInfo Demo" />
  97.     <TextBox
  98.         Name="textBox2"
  99.         Margin="10"
  100.         VerticalAlignment="Center"
  101.         FontSize="22"
  102.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  103.      <TextBlock
  104.          HorizontalAlignment="Center"
  105.          FontSize="18"
  106.          FontWeight="Bold"
  107.          Foreground="Red"
  108.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  109. </StackPanel>       Foreground="Red"
  110. <StackPanel Grid.Column="1">
  111.     <TextBlock
  112.         HorizontalAlignment="Center"
  113.         FontSize="18"
  114.         FontWeight="Bold"
  115.         Text="IDataErrorInfo Demo" />
  116.     <TextBox
  117.         Name="textBox2"
  118.         Margin="10"
  119.         VerticalAlignment="Center"
  120.         FontSize="22"
  121.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  122.      <TextBlock
  123.          HorizontalAlignment="Center"
  124.          FontSize="18"
  125.          FontWeight="Bold"
  126.          Foreground="Red"
  127.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  128. </StackPanel>       Text="!" />
  129.             </DockPanel>
  130.         </ControlTemplate>
  131.         
  132.     </Window.Resources>
  133.     <Grid>
  134.         <Grid.ColumnDefinitions>
  135.             <ColumnDefinition Width="1*" />
  136.             <ColumnDefinition Width="1*" />
  137.         </Grid.ColumnDefinitions>
  138.         <StackPanel Grid.Column="0">
  139.             <TextBlock
  140. <StackPanel Grid.Column="1">
  141.     <TextBlock
  142.         HorizontalAlignment="Center"
  143.         FontSize="18"
  144.         FontWeight="Bold"
  145.         Text="IDataErrorInfo Demo" />
  146.     <TextBox
  147.         Name="textBox2"
  148.         Margin="10"
  149.         VerticalAlignment="Center"
  150.         FontSize="22"
  151.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  152.      <TextBlock
  153.          HorizontalAlignment="Center"
  154.          FontSize="18"
  155.          FontWeight="Bold"
  156.          Foreground="Red"
  157.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  158. </StackPanel>   HorizontalAlignment="Center"
  159. <StackPanel Grid.Column="1">
  160.     <TextBlock
  161.         HorizontalAlignment="Center"
  162.         FontSize="18"
  163.         FontWeight="Bold"
  164.         Text="IDataErrorInfo Demo" />
  165.     <TextBox
  166.         Name="textBox2"
  167.         Margin="10"
  168.         VerticalAlignment="Center"
  169.         FontSize="22"
  170.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  171.      <TextBlock
  172.          HorizontalAlignment="Center"
  173.          FontSize="18"
  174.          FontWeight="Bold"
  175.          Foreground="Red"
  176.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  177. </StackPanel>   FontSize="18"
  178. <StackPanel Grid.Column="1">
  179.     <TextBlock
  180.         HorizontalAlignment="Center"
  181.         FontSize="18"
  182.         FontWeight="Bold"
  183.         Text="IDataErrorInfo Demo" />
  184.     <TextBox
  185.         Name="textBox2"
  186.         Margin="10"
  187.         VerticalAlignment="Center"
  188.         FontSize="22"
  189.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  190.      <TextBlock
  191.          HorizontalAlignment="Center"
  192.          FontSize="18"
  193.          FontWeight="Bold"
  194.          Foreground="Red"
  195.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  196. </StackPanel>   FontWeight="Bold"
  197. <StackPanel Grid.Column="1">
  198.     <TextBlock
  199.         HorizontalAlignment="Center"
  200.         FontSize="18"
  201.         FontWeight="Bold"
  202.         Text="IDataErrorInfo Demo" />
  203.     <TextBox
  204.         Name="textBox2"
  205.         Margin="10"
  206.         VerticalAlignment="Center"
  207.         FontSize="22"
  208.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  209.      <TextBlock
  210.          HorizontalAlignment="Center"
  211.          FontSize="18"
  212.          FontWeight="Bold"
  213.          Foreground="Red"
  214.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  215. </StackPanel>   Text="Validation Demo" />
  216.             <TextBox
  217. <StackPanel Grid.Column="1">
  218.     <TextBlock
  219.         HorizontalAlignment="Center"
  220.         FontSize="18"
  221.         FontWeight="Bold"
  222.         Text="IDataErrorInfo Demo" />
  223.     <TextBox
  224.         Name="textBox2"
  225.         Margin="10"
  226.         VerticalAlignment="Center"
  227.         FontSize="22"
  228.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  229.      <TextBlock
  230.          HorizontalAlignment="Center"
  231.          FontSize="18"
  232.          FontWeight="Bold"
  233.          Foreground="Red"
  234.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  235. </StackPanel>   Name="textBox1"
  236. <StackPanel Grid.Column="1">
  237.     <TextBlock
  238.         HorizontalAlignment="Center"
  239.         FontSize="18"
  240.         FontWeight="Bold"
  241.         Text="IDataErrorInfo Demo" />
  242.     <TextBox
  243.         Name="textBox2"
  244.         Margin="10"
  245.         VerticalAlignment="Center"
  246.         FontSize="22"
  247.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  248.      <TextBlock
  249.          HorizontalAlignment="Center"
  250.          FontSize="18"
  251.          FontWeight="Bold"
  252.          Foreground="Red"
  253.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  254. </StackPanel>   Height="30"
  255. <StackPanel Grid.Column="1">
  256.     <TextBlock
  257.         HorizontalAlignment="Center"
  258.         FontSize="18"
  259.         FontWeight="Bold"
  260.         Text="IDataErrorInfo Demo" />
  261.     <TextBox
  262.         Name="textBox2"
  263.         Margin="10"
  264.         VerticalAlignment="Center"
  265.         FontSize="22"
  266.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  267.      <TextBlock
  268.          HorizontalAlignment="Center"
  269.          FontSize="18"
  270.          FontWeight="Bold"
  271.          Foreground="Red"
  272.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  273. </StackPanel>   Margin="10"
  274. <StackPanel Grid.Column="1">
  275.     <TextBlock
  276.         HorizontalAlignment="Center"
  277.         FontSize="18"
  278.         FontWeight="Bold"
  279.         Text="IDataErrorInfo Demo" />
  280.     <TextBox
  281.         Name="textBox2"
  282.         Margin="10"
  283.         VerticalAlignment="Center"
  284.         FontSize="22"
  285.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  286.      <TextBlock
  287.          HorizontalAlignment="Center"
  288.          FontSize="18"
  289.          FontWeight="Bold"
  290.          Foreground="Red"
  291.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  292. </StackPanel>   FontSize="22"
  293. <StackPanel Grid.Column="1">
  294.     <TextBlock
  295.         HorizontalAlignment="Center"
  296.         FontSize="18"
  297.         FontWeight="Bold"
  298.         Text="IDataErrorInfo Demo" />
  299.     <TextBox
  300.         Name="textBox2"
  301.         Margin="10"
  302.         VerticalAlignment="Center"
  303.         FontSize="22"
  304.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  305.      <TextBlock
  306.          HorizontalAlignment="Center"
  307.          FontSize="18"
  308.          FontWeight="Bold"
  309.          Foreground="Red"
  310.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  311. </StackPanel>   Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
  312. <StackPanel Grid.Column="1">
  313.     <TextBlock
  314.         HorizontalAlignment="Center"
  315.         FontSize="18"
  316.         FontWeight="Bold"
  317.         Text="IDataErrorInfo Demo" />
  318.     <TextBox
  319.         Name="textBox2"
  320.         Margin="10"
  321.         VerticalAlignment="Center"
  322.         FontSize="22"
  323.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  324.      <TextBlock
  325.          HorizontalAlignment="Center"
  326.          FontSize="18"
  327.          FontWeight="Bold"
  328.          Foreground="Red"
  329.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  330. </StackPanel>   <TextBox.Text>
  331. <StackPanel Grid.Column="1">
  332.     <TextBlock
  333.         HorizontalAlignment="Center"
  334.         FontSize="18"
  335.         FontWeight="Bold"
  336.         Text="IDataErrorInfo Demo" />
  337.     <TextBox
  338.         Name="textBox2"
  339.         Margin="10"
  340.         VerticalAlignment="Center"
  341.         FontSize="22"
  342.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  343.      <TextBlock
  344.          HorizontalAlignment="Center"
  345.          FontSize="18"
  346.          FontWeight="Bold"
  347.          Foreground="Red"
  348.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  349. </StackPanel>       <Binding Path="TestField1" UpdateSourceTrigger="PropertyChanged">
  350. <StackPanel Grid.Column="1">
  351.     <TextBlock
  352.         HorizontalAlignment="Center"
  353.         FontSize="18"
  354.         FontWeight="Bold"
  355.         Text="IDataErrorInfo Demo" />
  356.     <TextBox
  357.         Name="textBox2"
  358.         Margin="10"
  359.         VerticalAlignment="Center"
  360.         FontSize="22"
  361.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  362.      <TextBlock
  363.          HorizontalAlignment="Center"
  364.          FontSize="18"
  365.          FontWeight="Bold"
  366.          Foreground="Red"
  367.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  368. </StackPanel>           <Binding.ValidationRules>
  369. <StackPanel Grid.Column="1">
  370.     <TextBlock
  371.         HorizontalAlignment="Center"
  372.         FontSize="18"
  373.         FontWeight="Bold"
  374.         Text="IDataErrorInfo Demo" />
  375.     <TextBox
  376.         Name="textBox2"
  377.         Margin="10"
  378.         VerticalAlignment="Center"
  379.         FontSize="22"
  380.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  381.      <TextBlock
  382.          HorizontalAlignment="Center"
  383.          FontSize="18"
  384.          FontWeight="Bold"
  385.          Foreground="Red"
  386.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  387. </StackPanel><StackPanel Grid.Column="1">
  388.     <TextBlock
  389.         HorizontalAlignment="Center"
  390.         FontSize="18"
  391.         FontWeight="Bold"
  392.         Text="IDataErrorInfo Demo" />
  393.     <TextBox
  394.         Name="textBox2"
  395.         Margin="10"
  396.         VerticalAlignment="Center"
  397.         FontSize="22"
  398.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  399.      <TextBlock
  400.          HorizontalAlignment="Center"
  401.          FontSize="18"
  402.          FontWeight="Bold"
  403.          Foreground="Red"
  404.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  405. </StackPanel>  <local:IntegerValidationRule
  406. <StackPanel Grid.Column="1">
  407.     <TextBlock
  408.         HorizontalAlignment="Center"
  409.         FontSize="18"
  410.         FontWeight="Bold"
  411.         Text="IDataErrorInfo Demo" />
  412.     <TextBox
  413.         Name="textBox2"
  414.         Margin="10"
  415.         VerticalAlignment="Center"
  416.         FontSize="22"
  417.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  418.      <TextBlock
  419.          HorizontalAlignment="Center"
  420.          FontSize="18"
  421.          FontWeight="Bold"
  422.          Foreground="Red"
  423.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  424. </StackPanel><StackPanel Grid.Column="1">
  425.     <TextBlock
  426.         HorizontalAlignment="Center"
  427.         FontSize="18"
  428.         FontWeight="Bold"
  429.         Text="IDataErrorInfo Demo" />
  430.     <TextBox
  431.         Name="textBox2"
  432.         Margin="10"
  433.         VerticalAlignment="Center"
  434.         FontSize="22"
  435.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  436.      <TextBlock
  437.          HorizontalAlignment="Center"
  438.          FontSize="18"
  439.          FontWeight="Bold"
  440.          Foreground="Red"
  441.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  442. </StackPanel>      MaxVal="999"
  443. <StackPanel Grid.Column="1">
  444.     <TextBlock
  445.         HorizontalAlignment="Center"
  446.         FontSize="18"
  447.         FontWeight="Bold"
  448.         Text="IDataErrorInfo Demo" />
  449.     <TextBox
  450.         Name="textBox2"
  451.         Margin="10"
  452.         VerticalAlignment="Center"
  453.         FontSize="22"
  454.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  455.      <TextBlock
  456.          HorizontalAlignment="Center"
  457.          FontSize="18"
  458.          FontWeight="Bold"
  459.          Foreground="Red"
  460.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  461. </StackPanel><StackPanel Grid.Column="1">
  462.     <TextBlock
  463.         HorizontalAlignment="Center"
  464.         FontSize="18"
  465.         FontWeight="Bold"
  466.         Text="IDataErrorInfo Demo" />
  467.     <TextBox
  468.         Name="textBox2"
  469.         Margin="10"
  470.         VerticalAlignment="Center"
  471.         FontSize="22"
  472.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  473.      <TextBlock
  474.          HorizontalAlignment="Center"
  475.          FontSize="18"
  476.          FontWeight="Bold"
  477.          Foreground="Red"
  478.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  479. </StackPanel>      MinVal="5" />
  480. <StackPanel Grid.Column="1">
  481.     <TextBlock
  482.         HorizontalAlignment="Center"
  483.         FontSize="18"
  484.         FontWeight="Bold"
  485.         Text="IDataErrorInfo Demo" />
  486.     <TextBox
  487.         Name="textBox2"
  488.         Margin="10"
  489.         VerticalAlignment="Center"
  490.         FontSize="22"
  491.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  492.      <TextBlock
  493.          HorizontalAlignment="Center"
  494.          FontSize="18"
  495.          FontWeight="Bold"
  496.          Foreground="Red"
  497.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  498. </StackPanel>           </Binding.ValidationRules>
  499. <StackPanel Grid.Column="1">
  500.     <TextBlock
  501.         HorizontalAlignment="Center"
  502.         FontSize="18"
  503.         FontWeight="Bold"
  504.         Text="IDataErrorInfo Demo" />
  505.     <TextBox
  506.         Name="textBox2"
  507.         Margin="10"
  508.         VerticalAlignment="Center"
  509.         FontSize="22"
  510.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  511.      <TextBlock
  512.          HorizontalAlignment="Center"
  513.          FontSize="18"
  514.          FontWeight="Bold"
  515.          Foreground="Red"
  516.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  517. </StackPanel>       </Binding>
  518. <StackPanel Grid.Column="1">
  519.     <TextBlock
  520.         HorizontalAlignment="Center"
  521.         FontSize="18"
  522.         FontWeight="Bold"
  523.         Text="IDataErrorInfo Demo" />
  524.     <TextBox
  525.         Name="textBox2"
  526.         Margin="10"
  527.         VerticalAlignment="Center"
  528.         FontSize="22"
  529.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  530.      <TextBlock
  531.          HorizontalAlignment="Center"
  532.          FontSize="18"
  533.          FontWeight="Bold"
  534.          Foreground="Red"
  535.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  536. </StackPanel>   </TextBox.Text>
  537.             </TextBox>
  538.         </StackPanel>
  539.     </Grid>
  540. </Window>
复制代码
最后在窗体后台绑定 ViewModel:
  1. public MainWindow()
  2. {
  3.     InitializeComponent();
  4.     this.DataContext =  TestViewModel.Instance;
  5. }
复制代码
测试


  • 为空时,出现红色叹号,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[string columnName]。这两个成员允许你在数据绑定时提供验证错误信息。
基本用法

接下来,在程序里添加 TextBox,命名为”textbox2“,并添加一个 TextBlock 绑定 Error 展示在界面。
  1. <StackPanel Grid.Column="1">
  2.     <TextBlock
  3.         HorizontalAlignment="Center"
  4.         FontSize="18"
  5.         FontWeight="Bold"
  6.         Text="IDataErrorInfo Demo" />
  7.     <TextBox
  8.         Name="textBox2"
  9.         Margin="10"
  10.         VerticalAlignment="Center"
  11.         FontSize="22"
  12.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  13.      <TextBlock
  14.          HorizontalAlignment="Center"
  15.          FontSize="18"
  16.          FontWeight="Bold"
  17.          Foreground="Red"
  18.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  19. </StackPanel>
复制代码
后台 TestViweModel 实现 IDataErrorInfo,依旧是判断上限值和下限值,此处不判断空,是因为后台 TestField2 类型是Int,为空时不会赋值,代码如下:
  1. public class TestViewModel : INotifyPropertyChanged, IDataErrorInfo{    //省略上文已有代码..。        private string error;    public string Error    {        get => error;        set        {            error = value; OnPropertyChanged(nameof(Error));        }    }    public string this[string columnName]    {        get        {            switch (columnName)            {<StackPanel Grid.Column="1">
  2.     <TextBlock
  3.         HorizontalAlignment="Center"
  4.         FontSize="18"
  5.         FontWeight="Bold"
  6.         Text="IDataErrorInfo Demo" />
  7.     <TextBox
  8.         Name="textBox2"
  9.         Margin="10"
  10.         VerticalAlignment="Center"
  11.         FontSize="22"
  12.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  13.      <TextBlock
  14.          HorizontalAlignment="Center"
  15.          FontSize="18"
  16.          FontWeight="Bold"
  17.          Foreground="Red"
  18.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  19. </StackPanel>   case nameof(TestField2):<StackPanel Grid.Column="1">
  20.     <TextBlock
  21.         HorizontalAlignment="Center"
  22.         FontSize="18"
  23.         FontWeight="Bold"
  24.         Text="IDataErrorInfo Demo" />
  25.     <TextBox
  26.         Name="textBox2"
  27.         Margin="10"
  28.         VerticalAlignment="Center"
  29.         FontSize="22"
  30.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  31.      <TextBlock
  32.          HorizontalAlignment="Center"
  33.          FontSize="18"
  34.          FontWeight="Bold"
  35.          Foreground="Red"
  36.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  37. </StackPanel>       return CheckTestFild2();<StackPanel Grid.Column="1">
  38.     <TextBlock
  39.         HorizontalAlignment="Center"
  40.         FontSize="18"
  41.         FontWeight="Bold"
  42.         Text="IDataErrorInfo Demo" />
  43.     <TextBox
  44.         Name="textBox2"
  45.         Margin="10"
  46.         VerticalAlignment="Center"
  47.         FontSize="22"
  48.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  49.      <TextBlock
  50.          HorizontalAlignment="Center"
  51.          FontSize="18"
  52.          FontWeight="Bold"
  53.          Foreground="Red"
  54.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  55. </StackPanel>   default:<StackPanel Grid.Column="1">
  56.     <TextBlock
  57.         HorizontalAlignment="Center"
  58.         FontSize="18"
  59.         FontWeight="Bold"
  60.         Text="IDataErrorInfo Demo" />
  61.     <TextBox
  62.         Name="textBox2"
  63.         Margin="10"
  64.         VerticalAlignment="Center"
  65.         FontSize="22"
  66.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  67.      <TextBlock
  68.          HorizontalAlignment="Center"
  69.          FontSize="18"
  70.          FontWeight="Bold"
  71.          Foreground="Red"
  72.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  73. </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 range  in viewmodel.";        }        else        {            Error = string.Empty;        }<StackPanel Grid.Column="1">
  74.     <TextBlock
  75.         HorizontalAlignment="Center"
  76.         FontSize="18"
  77.         FontWeight="Bold"
  78.         Text="IDataErrorInfo Demo" />
  79.     <TextBox
  80.         Name="textBox2"
  81.         Margin="10"
  82.         VerticalAlignment="Center"
  83.         FontSize="22"
  84.         Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
  85.      <TextBlock
  86.          HorizontalAlignment="Center"
  87.          FontSize="18"
  88.          FontWeight="Bold"
  89.          Foreground="Red"
  90.          Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  91. </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】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具