zoukankan      html  css  js  c++  java
  • 稳扎稳打Silverlight(51) 4.0绑定之数据验证IDataErrorInfo, INotifyDataErrorInfo

    [索引页]
    [源码下载]


    稳扎稳打Silverlight(51) - 4.0绑定之数据验证IDataErrorInfo, INotifyDataErrorInfo



    作者:webabcd


    介绍
    Silverlight 4.0 数据验证:

    • IDataErrorInfo - 对数据实体类提供自定义验证支持。.NET Framework 也有此接口,可以方便移植 
    • INotifyDataErrorInfo - 对数据实体类提供自定义验证支持,比 IDataErrorInfo 功能更强大。INotifyDataErrorInfo 支持异步验证,这就意味着其可以通过验证方法调用 Web 服务和用回调方法更新错误集合来添加服务器端验证 



    在线DEMO
    http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html


    示例
    1、演示 IDataErrorInfo 的应用
    IDataErrorInfoModel.cs

    代码
    /*
     * IDataErrorInfo - 对数据实体类提供自定义验证支持。.NET Framework 也有此接口,可以方便移植
     *     string Error - 获取对象的验证错误信息
     *     string this[string columnName] - 获取对象的指定字段的验证错误信息
     
    */

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    namespace Silverlight40.Binding
    {
        
    public class IDataErrorInfoModel : System.ComponentModel.IDataErrorInfo
        {
            
    // 验证错误的提示信息
            private const string ID_ERROR = "id 不能小于 10";
            
    private const string NAME_ERROR = "name 不能包含空格";
            
    private const string NAME_WARNING = "name 不能小于 5 个字符";

            
    // 用于保存验证错误信息。key 保存所验证的字段名称;value 保存对应的字段的验证错误信息列表
            private Dictionary<String, List<String>> errors = new Dictionary<string, List<string>>();

            
    private int _id;
            [Display(Name 
    = "标识")]
            
    public int Id
            {
                
    get { return _id; }
                
    set 
                {
                    
    if (value > 1000)
                        
    throw new Exception("太大了");

                    
    if (IsIdValid(value) && _id != value) 
                        _id 
    = value; 
                }
            }

            
    private string _name;
            [Display(Name 
    = "名称")]
            
    public string Name
            {
                
    get { return _name; }
                
    set 
                { 
                    
    if (IsNameValid(value) && _name != value) 
                        _name 
    = value; 
                }
            }

            
    public bool IsIdValid(int value)
            {
                
    bool isValid = true;

                
    if (value < 10)
                {
                    AddError(
    "Id", ID_ERROR);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Id", ID_ERROR);
                }

                
    return isValid;
            }

            
    public bool IsNameValid(string value)
            {
                
    bool isValid = true;

                
    if (value.Contains(" "))
                {
                    AddError(
    "Name", NAME_ERROR);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Name", NAME_ERROR);
                }

                
    if (value.Length < 5)
                {
                    AddError(
    "Name", NAME_WARNING);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Name", NAME_WARNING);
                }

                
    return isValid;
            }
          
            
    public void AddError(string propertyName, string error)
            {
                
    if (!errors.ContainsKey(propertyName))
                    errors[propertyName] 
    = new List<string>();

                
    if (!errors[propertyName].Contains(error))
                    errors[propertyName].Add(error);
            }

            
    public void RemoveError(string propertyName, string error)
            {
                
    if (errors.ContainsKey(propertyName) && errors[propertyName].Contains(error))
                {
                    errors[propertyName].Remove(error);

                    
    if (errors[propertyName].Count == 0
                        errors.Remove(propertyName);
                }
            }



            
    public string Error
            {
                
    get { return errors.Count > 0 ? "有验证错误" : "没有验证错误"; }
            }

            
    public string this[string propertyName]
            {
                
    get 
                {
                    
    if (errors.ContainsKey(propertyName))
                        
    return string.Join(Environment.NewLine, errors[propertyName]);
                    
    else
                        
    return null;
                }
            }
        }
    }


    IDataErrorInfo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.Binding.IDataErrorInfo" 
               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:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               xmlns:sdk
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
               Title
    ="IDataErrorInfo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">

                
    <sdk:ValidationSummary Margin="3">
                    
    <sdk:ValidationSummary.Header>
                        错误列表:
                    
    </sdk:ValidationSummary.Header>
                
    </sdk:ValidationSummary>

                
    <!--
                    ValidatesOnExceptions - 指定绑定引擎是否报告验证过程中的异常信息
                    ValidatesOnDataErrors - 指定绑定引擎是否报告绑定数据实体上的 IDataErrorInfo 所实现的验证错误信息(通过 IDataErrorInfo 的 this[string columnName] 获取验证错误信息)
                    NotifyOnValidationError - 当出现验证错误时是否触发 BindingValidationError 事件
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Target="{Binding ElementName=txtId}" />
                    
    <TextBox Name="txtId" Text="{Binding Id, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" KeyDown="txtId_KeyDown"/>
                    
    <sdk:DescriptionViewer Description="id 不能小于 10"/>
                
    </StackPanel>

                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Target="{Binding ElementName=txtName}"/>
                    
    <TextBox Name="txtName" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" KeyDown="txtName_KeyDown"/>
                    
    <sdk:DescriptionViewer Description="name 不能包含空格且 name 不能小于 5 个字符"/>
                
    </StackPanel>
                
                
    <Button Name="btnSubmit" Content="获取验证信息" Click="btnSubmit_Click" />
                
            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    IDataErrorInfo.xaml.cs

    代码
    /*
     * 通过绑定实现了 IDataErrorInfo 接口的实体类来实现自定义数据验证功能
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    namespace Silverlight40.Binding
    {
        
    public partial class IDataErrorInfo : Page
        {
            IDataErrorInfoModel _model;

            
    public IDataErrorInfo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                _model 
    = new IDataErrorInfoModel() { Id = 100, Name = "webabcd" };
                LayoutRoot.DataContext 
    = _model;

                
    // BindingValidationError - 当有数据验证错误时所触发的事件。绑定时需要设置 NotifyOnValidationError=True
                txtId.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); };
                txtName.BindingValidationError 
    += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); };
            }

            
    private void txtId_KeyDown(object sender, KeyEventArgs e)
            {
                
    // 注:
                
    // BindingValidationError 事件只有在控件失去焦点才会被触发
                
    // 如果需要在控件没失去焦点的情况下产生验证效果,那么可以通过调用 BindingExpression.UpdateSource() 方法来实现

                
    // FrameworkElement.GetBindingExpression(DependencyProperty dp) - 获取 FrameworkElement 的指定属性上的绑定信息
                
    // BindingExpression.UpdateSource() - 将当前绑定信息立即发送到绑定方式为 TwoWay 的属性上
                if (e.Key == System.Windows.Input.Key.Enter)
                    txtId.GetBindingExpression(TextBox.TextProperty).UpdateSource();
            }

            
    private void txtName_KeyDown(object sender, KeyEventArgs e)
            {
                
    if (e.Key == System.Windows.Input.Key.Enter)
                    txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource();
            }

            
    private void btnSubmit_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(
    "验证信息:" + _model.Error);
            }
        }
    }



    2、演示 INotifyDataErrorInfo 的应用
    INotifyDataErrorInfoModel.cs

    代码
    /*
     * INotifyDataErrorInfo - 对数据实体类提供自定义验证支持,比 IDataErrorInfo 功能更强大。INotifyDataErrorInfo 支持异步验证,这就意味着其可以通过验证方法调用 Web 服务和用回调方法更新错误集合来添加服务器端验证
     *     bool HasErrors - 对象是否有验证错误信息
     *     event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged - 当对象的验证错误信息发生改变时所触发的事件
     *     IEnumerable GetErrors(string propertyName) - 获取对象的指定字段的验证错误信息
     
    */

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel;

    namespace Silverlight40.Binding
    {
        
    public class INotifyDataErrorInfoModel : System.ComponentModel.INotifyDataErrorInfo
        {
            
    // 验证错误的提示信息
            private const string ID_ERROR = "id 不能小于 10";
            
    private const string NAME_ERROR = "name 不能包含空格";
            
    private const string NAME_WARNING = "name 不能小于 5 个字符";

            
    // 用于保存验证错误信息。key 保存所验证的字段名称;value 保存对应的字段的验证错误信息列表
            private Dictionary<String, List<String>> errors = new Dictionary<string, List<string>>();

            
    private int _id;
            [Display(Name 
    = "标识")]
            
    public int Id
            {
                
    get { return _id; }
                
    set
                {
                    
    if (value > 1000)
                        
    throw new Exception("太大了");

                    
    if (IsIdValid(value) && _id != value)
                        _id 
    = value;
                }
            }

            
    private string _name;
            [Display(Name 
    = "名称")]
            
    public string Name
            {
                
    get { return _name; }
                
    set
                {
                    
    if (IsNameValid(value) && _name != value)
                        _name 
    = value;
                }
            }

            
    public bool IsIdValid(int value)
            {
                
    bool isValid = true;

                
    if (value < 10)
                {
                    AddError(
    "Id", ID_ERROR);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Id", ID_ERROR);
                }

                
    return isValid;
            }

            
    public bool IsNameValid(string value)
            {
                
    bool isValid = true;

                
    if (value.Contains(" "))
                {
                    AddError(
    "Name", NAME_ERROR);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Name", NAME_ERROR);
                }

                
    if (value.Length < 5)
                {
                    AddError(
    "Name", NAME_WARNING);
                    isValid 
    = false;
                }
                
    else
                {
                    RemoveError(
    "Name", NAME_WARNING);
                }

                
    return isValid;
            }

            
    public void AddError(string propertyName, string error)
            {
                
    if (!errors.ContainsKey(propertyName))
                    errors[propertyName] 
    = new List<string>();

                
    if (!errors[propertyName].Contains(error))
                {
                    errors[propertyName].Add(error);
                    RaiseErrorsChanged(propertyName);

                }
            }

            
    public void RemoveError(string propertyName, string error)
            {
                
    if (errors.ContainsKey(propertyName) && errors[propertyName].Contains(error))
                {
                    errors[propertyName].Remove(error);

                    
    if (errors[propertyName].Count == 0)
                        errors.Remove(propertyName);

                    RaiseErrorsChanged(propertyName);
                }
            }



            
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
            
    public void RaiseErrorsChanged(string propertyName)
            {
                
    if (ErrorsChanged != null)
                    ErrorsChanged(
    thisnew DataErrorsChangedEventArgs(propertyName));
            }

            
    public System.Collections.IEnumerable GetErrors(string propertyName)
            {
                
    if (errors.ContainsKey(propertyName))
                    
    return errors[propertyName];
                
    else
                    
    return null;
            }

            
    public bool HasErrors
            {
                
    get { return errors.Count > 0; }
            }
        }
    }


    INotifyDataErrorInfo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.Binding.INotifyDataErrorInfo" 
               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:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               xmlns:sdk
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
               Title
    ="INotifyDataErrorInfo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">

                
    <sdk:ValidationSummary Margin="3">
                    
    <sdk:ValidationSummary.Header>
                        错误列表:
                    
    </sdk:ValidationSummary.Header>
                
    </sdk:ValidationSummary>

                
    <!--
                    ValidatesOnExceptions - 指定绑定引擎是否报告验证过程中的异常信息
                    NotifyOnValidationError - 当出现验证错误时是否触发 BindingValidationError 事件
                
    -->
                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Target="{Binding ElementName=txtId}" />
                    
    <TextBox Name="txtId" Text="{Binding Id, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" KeyDown="txtId_KeyDown"/>
                    
    <sdk:DescriptionViewer Description="id 不能小于 10"/>
                
    </StackPanel>

                
    <StackPanel Orientation="Horizontal">
                    
    <sdk:Label Target="{Binding ElementName=txtName}"/>
                    
    <TextBox Name="txtName" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" KeyDown="txtName_KeyDown"/>
                    
    <sdk:DescriptionViewer Description="name 不能包含空格且 name 不能小于 5 个字符"/>
                
    </StackPanel>

                
    <Button Name="btnSubmit" Content="是否有验证错误" Click="btnSubmit_Click" />

            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    INotifyDataErrorInfo.xaml.cs

    代码
    /*
     * 通过绑定实现了 INotifyDataErrorInfo 接口的实体类来实现自定义数据验证功能
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    namespace Silverlight40.Binding
    {
        
    public partial class INotifyDataErrorInfo : Page
        {
            INotifyDataErrorInfoModel _model;

            
    public INotifyDataErrorInfo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                _model 
    = new INotifyDataErrorInfoModel() { Id = 100, Name = "webabcd" };
                LayoutRoot.DataContext 
    = _model;

                
    // BindingValidationError - 当有数据验证错误时所触发的事件。绑定时需要设置 NotifyOnValidationError=True
                txtId.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); };
                txtName.BindingValidationError 
    += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); };
            }

            
    private void txtId_KeyDown(object sender, KeyEventArgs e)
            {
                
    // 注:
                
    // BindingValidationError 事件只有在控件失去焦点才会被触发
                
    // 如果需要在控件没失去焦点的情况下产生验证效果,那么可以通过调用 BindingExpression.UpdateSource() 方法来实现

                
    // FrameworkElement.GetBindingExpression(DependencyProperty dp) - 获取 FrameworkElement 的指定属性上的绑定信息
                
    // BindingExpression.UpdateSource() - 将当前绑定信息立即发送到绑定方式为 TwoWay 的属性上
                if (e.Key == System.Windows.Input.Key.Enter)
                    txtId.GetBindingExpression(TextBox.TextProperty).UpdateSource();
            }

            
    private void txtName_KeyDown(object sender, KeyEventArgs e)
            {
                
    if (e.Key == System.Windows.Input.Key.Enter)
                    txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource();
            }

            
    private void btnSubmit_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(
    "是否有验证错误:" + _model.HasErrors.ToString());
            }
        }
    }



    注:
    Silverlight 2.0 下的绑定及数据验证:http://www.cnblogs.com/webabcd/archive/2008/11/20/1337190.html
    Silverlight 3.0 下的绑定:http://www.cnblogs.com/webabcd/archive/2009/09/03/1559240.html
    Silverlight 3.0 下的数据验证(依赖 DataAnnotations):http://www.cnblogs.com/webabcd/archive/2009/08/10/1542663.html


    OK
    [源码下载]

  • 相关阅读:
    bzoj1455-罗马游戏
    bzoj1206-[HNOI2005]虚拟内存
    bzoj2762-[JLOI2011]不等式组
    bzoj2729-[HNOI2012]排队
    [模板] 高精度加/减/乘
    bzoj1013-[JSOI2008]球形空间产生器
    bzoj1002-[FJOI2007]轮状病毒
    什么是Redis缓存穿透、缓存雪崩和缓存击穿
    CentOS 7 中英文桌面安装步骤详细图解
    Redis数据操作
  • 原文地址:https://www.cnblogs.com/webabcd/p/1821911.html
Copyright © 2011-2022 走看看