[XAML学习资料] 验证用户提供的数据ValidationRule
在打开对话框以及用户提供所需的数据时,对话框负责确保提供的数据有效,原因如下:
-
从安全角度讲,应验证所有输入。
-
从特定于域的角度讲,数据验证可防止该代码处理错误的数据,因为这样可能会引发异常。
-
从用户体验的角度讲,对话框可以通过向用户显示哪些输入数据无效来为用户提供帮助。
-
从性能角度讲,多层应用程序中的数据验证可以减少客户端和应用程序层之间的往返次数,尤其是在该应用程序由 Web 服务或基于服务器的数据库组成时。
若要验证 WPF 中的绑定控件,您需要定义验证规则,然后将其与该绑定关联。验证规则是派生自 ValidationRule 的自定义类。下面的示例演示验证规则 MarginValidationRule,该规则检查绑定值是否是 Double 以及是否位于指定的范围内。
2 using System.Windows.Controls;
3
4 namespace SDKSample
5 {
6 public class MarginValidationRule : ValidationRule
7 {
8 double minMargin;
9 double maxMargin;
10
11 public double MinMargin
12 {
13 get { return this.minMargin; }
14 set { this.minMargin = value; }
15 }
16
17 public double MaxMargin
18 {
19 get { return this.maxMargin; }
20 set { this.maxMargin = value; }
21 }
22
23 public override ValidationResult Validate(object value, CultureInfo cultureInfo)
24 {
25 double margin;
26
27 // Is a number?
28 if (!double.TryParse((string)value, out margin))
29 {
30 return new ValidationResult(false, "不是数字!");
31 }
32
33 // Is in range?
34 if ((margin < this.minMargin) || (margin > this.maxMargin))
35 {
36 string msg = string.Format("Margin必须在{0} 和{1}之间.", this.minMargin, this.maxMargin);
37 return new ValidationResult(false, msg);
38 }
39
40 // Number is valid
41 return new ValidationResult(true, null);
42 }
43 }
44 }
45
在XAML中将其与控件绑定,具体代码如下所示:
2 <TextBox.Text>
3 <Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
4 <Binding.ValidationRules>
5 <local:MarginValidationRule MinMargin="0" MaxMargin="10" />
6 </Binding.ValidationRules>
7 </Binding>
8 </TextBox.Text>
9 </TextBox>
10
如果在TextBox输入不符合规则的,将会提示上述返回的msg内容,并且 WPF 将在无效控件周围显示一个红色边框,这样就可以提示用户输入并非所需要的数据。在用户输入有效数据之前,WPF 不会将用户限制于无效的控件。这对于对话框来说是很有利的;无论数据是否有效,用户都应当能够在对话框中自由导航控件。但是,这意味着用户可以输入无效的数据,然后按“确定”按钮。因此,在按“确定”按钮时,您的代码还需要通过处理 Click 事件来验证对话框中的所有控件。
2 {
3 // Don't accept the dialog box if there is invalid data
4 if (!IsValid(this)) return;
5
6
7
8
9
10 }
11
12 // Validate all dependency objects in a window
13 bool IsValid(DependencyObject node)
14 {
15 // Check if dependency object was passed
16 if (node != null)
17 {
18 // Check if dependency object is valid.
19 // NOTE: Validation.GetHasError works for controls that have validation rules attached
20 bool isValid = !Validation.GetHasError(node);
21 if (!isValid)
22 {
23 // If the dependency object is invalid, and it can receive the focus,
24 // set the focus
25 if (node is IInputElement) Keyboard.Focus((IInputElement)node);
26 return false;
27 }
28 }
29
30 // If this dependency object is valid, check all child dependency objects
31 foreach (object subnode in LogicalTreeHelper.GetChildren(node))
32 {
33 if (subnode is DependencyObject)
34 {
35 // If a child dependency object is invalid, return false immediately,
36 // otherwise keep checking
37 if (IsValid((DependencyObject)subnode) == false) return false;
38 }
39 }
40
41 // All dependency objects are valid
42 return true;
43 }
44 }
45 }
46
这个和ASP.NET的客户端验证控件一样,客户端虽然验证了,但是服务端最好同时验证,以免非法入侵者不通过客户端直接向服务的发送数据!!!验证规则只是提示用户,最终数据还是要在程序中验证的!!! 此代码将在窗口上枚举所有依赖项对象。如果有任何一个对象无效(由 GetHasError 返回),则此无效的控件将获得焦点,IsValid 方法将返回 false 并将该窗口视为无效。一旦对话框有效,则可以安全地关闭并返回。在返回过程中,需要向调用函数返回一个结果。
注:本文大部分内容和例子来自于MSDN!