zoukankan      html  css  js  c++  java
  • WPF中的数据验证

    WPF提供了非常好的数据验证模式。

     具体不理解的请参考《Validation in Windows Presentation Foundation

    如果让你设计在V-VM-M 中数据的验证 ,你更喜欢把它放到那一层呢?当然如果我们可以说那一层都无所谓,比较数据都是通过View输入的。最终的反馈也是在View层显示,那View层是最直接最方便的。 那WPF设计者的确为之中方式提供了很方便的编写方式。只要在Binding中使用ValidationRules指定具体的验证规则就OK了,而且一般来说我们要验证的数据不会太多,无非是不能为空,或者满足某个正则的约定。所以这个已经非常方便了。

     由于某些原因有很多时候我们的Model层可能本身就有了ValidationAttribute特性。那我们应该去应用这个特性。当然还有一个理由就是我们的数据对象被多出创建,或者说我们不想在XAML中每次都填写验证方式。

    那么我们可以这样去写。

    代码
    public abstract class ValidationViewModelBase : ViewModelBase, IDataErrorInfo
      {
        
    private readonly TypesContent _typesContent;

        
    private readonly Type _thisType;

        
    protected ValidationViewModelBase()
        {
          
    this._thisType = GetType();
          
    this._typesContent = new TypesContent(this._thisType);
        }

        
    #region Implementation of IDataErrorInfo

        
    public string this[string columnName]
        {
          
    get
          {
            PropertyInfo info 
    = this._typesContent.GetPropertyInfo(
              
    this._thisType, columnName);

            var validationAttributes 
    =
              
    this._typesContent.GetValidationAttribute(this._thisType, columnName);

            var value 
    = info.GetValue(thisnull);

            var errors 
    = new List<string>();

            
    foreach (var validationAttribute in validationAttributes)
            {
              
    if (!validationAttribute.IsValid(value))
              {
                errors.Add(validationAttribute.ErrorMessage);
              }
            }
            
            OnPropertyChanged(
    "Error");

            
    return string.Join(Environment.NewLine, errors.ToArray());
          }
        }

        
    public string Error
        {
          
    get
          {
            var propertyInfos 
    = this._typesContent.GetPropertInfos(this._thisType);
            var errorlist 
    = new List<string>();

            
    foreach (var info in propertyInfos)
            {
              var validationAttributes 
    =
                
    this._typesContent.GetValidationAttribute(
                  
    this._thisType, info.Name);

              var value 
    = info.GetValue(thisnull);

              var errors 
    = validationAttributes.Where(v => !v.IsValid(value))
                .Select(v 
    => v.ErrorMessage).ToArray();
              errorlist.AddRange(errors);
            }

            
    return string.Join(Environment.NewLine, errorlist.ToArray());
          }
        }

        
    #endregion

        
    private class TypePropertyContent
        {
          
    private readonly Type _type;

          
    private readonly Dictionary<string, PropertyInfo> _propertyInfos =
            
    new Dictionary<string, PropertyInfo>();

          
    private readonly Dictionary<string, ValidationAttribute[]> _validators =
            
    new Dictionary<string, ValidationAttribute[]>();

          
    public TypePropertyContent(Type type)
          {
            
    this._type = type;
            
    this.LoadData();
          }

          
    private void LoadData()
          {
            var classType 
    = this._type;
            var properties 
    = classType.GetProperties();
            
    foreach (var propertyInfo in properties)
            {
              var customAttributes 
    =
                propertyInfo.GetCustomAttributes(
                  
    typeof(ValidationAttribute), true);
              
    if (customAttributes.Length > 0)
              {
                
    this._validators.Add(
                  propertyInfo.Name, (ValidationAttribute[]) customAttributes);
                
    this._propertyInfos.Add(propertyInfo.Name, propertyInfo);
              }
            }
          }

          
    public PropertyInfo GetPropertInfo(string propertyName)
          {
            
    return this._propertyInfos.ContainsKey(propertyName)
                  
    ? this._propertyInfos[propertyName]
                  : 
    null;
          }

          
    public PropertyInfo[] GetPropertInfos()
          {
            
    return this._propertyInfos.Values.ToArray();
          }

          
    public ValidationAttribute[] GetValidationAttribute(string propertyName)
          {
            
    return this._validators.ContainsKey(propertyName)
                  
    ? this._validators[propertyName]
                  : 
    null;
          }
        }

        
    private class TypesContent
        {
          
    private static readonly Dictionary<Type, TypePropertyContent> _types =
            
    new Dictionary<Type, TypePropertyContent>();

          
    public TypesContent(Type type)
          {
            
    if (!_types.ContainsKey(type))
            {
              _types.Add(type, 
    new TypePropertyContent(type));
            }
          }

          
    public PropertyInfo GetPropertyInfo(Type type, string propertyName)
          {
            
    if (_types.ContainsKey(type))
            {
              var propertyContent 
    = _types[type];
              
    return propertyContent.GetPropertInfo(propertyName);
            }

            
    return null;
          }

          
    public ValidationAttribute[] GetValidationAttribute(
            Type type, 
    string propertyName)
          {
            
    if (_types.ContainsKey(type))
            {
              var typePropertyContent 
    = _types[type];
              
    return typePropertyContent.GetValidationAttribute(propertyName);
            }

            
    return null;
          }

          
    public PropertyInfo[] GetPropertInfos(Type type)
          {
            
    return _types.ContainsKey(type) ? _types[type].GetPropertInfos() : null;
          }
        }
      }
      
    public class ViewModelBase : INotifyPropertyChanged
      {
        
    #region INotifyPropertyChanged 

        
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

        
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
        {
          
    this.PropertyChanged(this, eventArgs);
        }

        
    protected virtual void OnPropertyChanged(string propertyName)
        {
          
    this.PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
        }

        
    #endregion
      }
      
      
    //ViewModel
       
     
    public class PersonViewModel : ValidationViewModelBase
      {
        
    private string _name;

        [RegularExpression(
    @"^\w+$", ErrorMessage = "format error")]
        
    public string Name
        {
          
    get
          {
            
    return this._name;
          }

          
    set
          {
            
    this._name = value;
            OnPropertyChanged(
    "Name");
          }
        }
      }
    //View like this:

    <TextBox>
      
    <TextBox.Text>
        
    <Binding Path=".Name"
             Mode
    ="TwoWay"
             UpdateSourceTrigger
    ="PropertyChanged"
             ValidatesOnDataErrors
    ="True"
             ValidatesOnExceptions
    ="True"
             NotifyOnValidationError
    ="True">
        
    </Binding>
      
    </TextBox.Text>
    </TextBox>
  • 相关阅读:
    VC 6.0 编译器的使用帮助
    生成可执行jar文件(转)
    DataGridView填充、更新、删除(多行)Sql Express 2005数据库
    访问域服务器修改密码,报“未知的身份验证机制”的错误搞定!
    尝试用Word2007发布博客
    iBatisNet Tutorial
    Asp.net 技巧集合
    TableAdapter 无法插入或更新Access数据库
    OrcasBeta1 installed 玩一玩Silverlight
    Microsoft .NET Compact Framework 开发常见问题解答从msdn上找到。
  • 原文地址:https://www.cnblogs.com/cuiweifu/p/Validation_Data_on_WPF.html
Copyright © 2011-2022 走看看