四月 29, 2010

使用WPF提供的数据验证机制

Written by

在用户通过WPF对话框窗口提供所需的数据时,对话框负责确保提供的数据有效,原因如下:

  • 从安全角度讲,应验证所有输入。

  • 从特定于域的角度讲,数据验证可防止该代码处理错误的数据,因为这样可能会引发异常。

  • 从用户体验的角度讲,对话框可以通过向用户显示哪些输入数据无效来为用户提供帮助。

  • 从性能角度讲,多层应用程序中的数据验证可以减少客户端和应用程序层之间的往返次数,尤其是在该应用程序由 Web 服务或基于服务器的数据库组成时。

若要验证 WPF 中的绑定控件,您需要定义验证规则,然后将其与该绑定关联。验证规则是派生自 ValidationRule 的自定义类。下面的示例演示验证规则 MarginValidationRule,该规则检查绑定值是否是 Double 以及是否位于指定的范围内。

C#

using System.Globalization;
using System.Windows.Controls;

namespace SDKSample
{
    public class MarginValidationRule : ValidationRule
    {
        double minMargin;
        double maxMargin;

        public double MinMargin
        {
            get { return this.minMargin; }
            set { this.minMargin = value; }
        }

        public double MaxMargin
        {
            get { return this.maxMargin; }
            set { this.maxMargin = value; }
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            double margin;

            // Is a number?
            if (!double.TryParse((string)value, out margin))
            {
                return new ValidationResult(false, “Not a number.”);
            }

            // Is in range?
            if ((margin < this.minMargin) || (margin > this.maxMargin))
            {
                string msg = string.Format(“Margin must be between {0} and {1}.”, this.minMargin, this.maxMargin);
                return new ValidationResult(false, msg);
            }

            // Number is valid
            return new ValidationResult(true, null);
        }
    }
}

在此代码中,通过重写 Validate 方法来实现验证规则的验证逻辑,该方法对数据进行验证并返回相应的 ValidationResult。

若要将验证规则与绑定控件关联,您需要使用以下标记。

XAML

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MarginsDialogBox"
    xmlns:local="clr-namespace:SDKSample"
    Title="Margins"
    Height="190"
    Width="300"
    MinHeight="10"
    MinWidth="300"
    ResizeMode="CanResizeWithGrip"
    ShowInTaskbar="False"
    WindowStartupLocation="CenterOwner" 
    FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">

  <Grid>



...


<Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
<TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
  <TextBox.Text>
    <Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <local:MarginValidationRule MinMargin="0" MaxMargin="10" />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>


...


</Window>

对验证规则进行关联之后,WPF 将在数据输入绑定控件时自动应用该规则。如果控件包含无效的数据,则 WPF 将在无效控件周围显示一个红色边框,如下图所示。

untitled

在用户输入有效数据之前,WPF 不会将用户限制于无效的控件。这对于对话框来说是很有利的;无论数据是否有效,用户都应当能够在对话框中自由导航控件。但是,这意味着用户可以输入无效的数据,然后按“确定”按钮。因此,在按“确定”按钮时,您的代码还需要通过处理 Click 事件来验证对话框中的所有控件。

C#

using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {

void okButton_Click(object sender, RoutedEventArgs e)
{
    // Don’t accept the dialog box if there is invalid data
    if (!IsValid(this)) return;

        }

        // Validate all dependency objects in a window
        bool IsValid(DependencyObject node)
        {
            // Check if dependency object was passed
            if (node != null)
            {
                // Check if dependency object is valid.
                // NOTE: Validation.GetHasError works for controls that have validation rules attached
                bool isValid = !Validation.GetHasError(node);
                if (!isValid)
                {
                    // If the dependency object is invalid, and it can receive the focus,
                    // set the focus
                    if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                    return false;
                }
            }

            // If this dependency object is valid, check all child dependency objects
            foreach (object subnode in LogicalTreeHelper.GetChildren(node))
            {
                if (subnode is DependencyObject)
                {  
                    // If a child dependency object is invalid, return false immediately,
                    // otherwise keep checking
                    if (IsValid((DependencyObject)subnode) == false) return false;
                }
            }

            // All dependency objects are valid
            return true;
        }
    }
}

此代码将在窗口上枚举所有依赖项对象。如果有任何一个对象无效(由 GetHasError 返回),则此无效的控件将获得焦点,IsValid 方法将返回 false 并将该窗口视为无效。

一旦对话框有效,则可以安全地关闭并返回。在返回过程中,需要向调用函数返回一个结果。

 

本文来自msdn,一切归msdn所有。

Category : .NetC#Window$WPF其他

Tags :

发表评论

电子邮件地址不会被公开。

Proudly powered by WordPress and Sweet Tech Theme