WPF 数据验证

  在软件UI界面录入数据时候,为了保证数据的正确、有效、规范性,很多情况下都要验证数据的有效性。比如录入某个人的信息,那么我们就需要对这个人的姓名验证是否为空字符串,年龄是否为有效数字,性别是否为男或女等等。

  在WPF开发中,数据的验证和数据绑定结合在一起,实现起来很优雅。我们可以让数据Model(模型)实现IDataErrorInfo接口来实现每个属性的验证逻辑。或者自定义一个继承自ValidationRule的类来实现验证逻辑。然后在Xaml中提供控件的ErrorTemplate模板,就可以得到很好的验证效果。下面提供一个样例代码:

  

后台数据
 1  public class Person : IDataErrorInfo
 2      {
 3          public string Name { get; set; }
 4  
 5          public int Age { get; set; }
 6  
 7          public string Sex { get; set; }
 8  
 9          public string Error
10          {
11              get { return "输入字符串无效"; }
12          }
13  
14          public string this[string columnName]
15          {
16              get
17              {
18                  string msg = string.Empty;
19                  switch (columnName)
20                  {
21                      case "Name":
22                          {
23                              if (string.IsNullOrEmpty(this.Name.Trim()))
24                              {
25                                  msg = "*请完善姓名内容";
26                              }
27                              break;
28                          }
29                      case "Age":
30                          {
31                              if (this.Age < 0 || this.Age > 120)
32                              {
33                                  msg = "*年龄范围为{0-120}之间";
34                              }
35                              break;
36                          }
37                      case "Sex":
38                          {
39                              if (string.IsNullOrEmpty(this.Sex.Trim()) ||
40                                 !(this.Sex.Trim() == "Boy" || this.Sex.Trim() == "Girl"))
41                              {
42                                  msg = "*你确定你既不是Boy也不是Girl吗?";
43                              }
44                              break;
45                          }
46                  }
47                  return msg;
48              }
49          }
50      }
51  
52      public class AgeValidate : ValidationRule
53      {
54          private int minAge;
55          public int MinAge
56          {
57              get { return minAge; }
58              set { minAge = value; }
59          }
60  
61          private int maxAge;
62          public int MaxAge
63          {
64              get { return maxAge; }
65              set { maxAge = value; }
66          }
67  
68          public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
69          {
70              int age;
71              string msg = string.Format("请输入大于{0}小于{1}的数字", minAge, maxAge);
72              if (int.TryParse(value.ToString(), out age))
73              {
74                  if (age < minAge || age > maxAge)
75                      return new ValidationResult(false, msg);
76                  else
77                      return new ValidationResult(true, null);
78              }
79              else
80              {
81                  return new ValidationResult(false, "请输入数字");
82              }
83          }
84      }
85 
86   public MainWindow()
87          {
88              InitializeComponent();
89  
90              Person ZhangSan = new Person()
91              {
92                  Age = 20,
93                  Name = "ZhangSan",
94                  Sex = "Boy"
95              };
96              this.DataContext = ZhanSan;
97  
98          }
UI代码
 1  <Window.Resources>
 2          <local:Converter x:Key="MarginConverter"></local:Converter>
 3          <Style TargetType="TextBox">
 4              <Setter Property="Width" Value="120"></Setter>
 5              <Setter Property="Margin" Value="5"></Setter>
 6              <Setter Property="VerticalAlignment" Value="Center"></Setter>
 7          </Style> 
 8          <Style TargetType="TextBlock">
 9              <Setter Property="MinWidth" Value="50"></Setter>
10              <Setter Property="Margin" Value="5"></Setter>
11              <Setter Property="VerticalAlignment" Value="Center"></Setter>
12          </Style>
13          <ControlTemplate x:Key="ErrorTemplate">
14              <Canvas Panel.ZIndex="100">
15                  <Border BorderBrush="Red" BorderThickness="1">
16                      <AdornedElementPlaceholder Name="MyAdorner"/>
17                  </Border>
18                  <TextBlock Foreground="Red" FontSize="12" 
19                             Margin="{Binding ElementName=MyAdorner, Path=ActualWidth, Converter={StaticResource MarginConverter}}"
20                             Text="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
21                  </TextBlock>
22              </Canvas>
23          </ControlTemplate>
24      </Window.Resources>
25 
26   <StackPanel>
27              <WrapPanel>
28                  <TextBlock>Name:</TextBlock>
29                  <TextBox Text="{Binding Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
30                           Validation.ErrorTemplate="{StaticResource ErrorTemplate}"></TextBox>
31                  <TextBlock>Age:</TextBlock>
32                  <TextBox  Validation.ErrorTemplate="{StaticResource ErrorTemplate}">
33                      <TextBox.Text>
34                          <Binding Path="Age"  ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged"
35                                   NotifyOnValidationError="True">
36                              <Binding.ValidationRules>
37                                  <local:AgeValidate MaxAge="99" MinAge="1"></local:AgeValidate>
38                              </Binding.ValidationRules>
39                          </Binding>
40                      </TextBox.Text>
41                  </TextBox>
42              </WrapPanel>
43              <WrapPanel>
44                  <TextBlock>Sex:</TextBlock>
45                  <TextBox Text="{Binding Path=Sex, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
46                           Validation.ErrorTemplate="{StaticResource ErrorTemplate}"></TextBox>
47              </WrapPanel>
48              <WrapPanel>
49                  <TextBlock>Age:</TextBlock>
50                  <TextBox Validation.ErrorTemplate="{StaticResource ErrorTemplate}">
51                      <TextBox.Text>
52                          <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True"> 
53                          </Binding>
54                      </TextBox.Text>
55                  </TextBox>
56              </WrapPanel> 
57  </StackPanel>
Converter Class
 1      public class Converter : IValueConverter
 2      {
 3          public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 4          {
 5              if (value is double)
 6              {
 7                  return new Thickness((double)value + 5, 3, 5, 5);
 8              }
 9              else return value;
10          }
11  
12          public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
13          {
14              throw new NotImplementedException();
15          }
16      }

注意:1. xaml中验证时机 UpdateSourceTrigger="PropertyChanged"表示属性修改后马上验证;

   2. ErrorTemplate 中TextBlock的 Text="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">的实现,这里Path=AdornedElement指的就是MyAdorner所装饰的元素,也就是我们需要验证的控件。因此获取的是该控件的(Validation.Errors)[0].ErrorContent 验证错误信息。

posted @ 2012-09-16 12:11  rpoplar  阅读(1114)  评论(0编辑  收藏  举报