编程语言
首页 > 编程语言> > c# – 使用数据注释的WPF MVVM验证

c# – 使用数据注释的WPF MVVM验证

作者:互联网

我是wpf mvvm架构的新手.插件更新正在使用linq到sql.I需要使用数据注释进行验证.我们如何使用数据注释提供验证.任何人都可以给出一些好的例子吗?

我的模型是

namespace EmployeeApp.Model
{
    public class Employee : ObservableObject
    {
        #region Constructor
        public Employee(int empId = 0, string empName = "", int age = 0)
        {
            _empId = empId;
            _empName = empName;
            _age = age;

        }
        #endregion

        #region Properties
        private int _empId = 0;

        public int EmpId
        {
            get { return _empId; }
            set
            {
                _empId = value;
                RaisePropertyChangedEvent("ID");
            }
        }

        private string _empName = string.Empty;

        public string EmpName
        {
            get { return _empName; }
            set
            {
                _empName = value;
                RaisePropertyChangedEvent("Name");
            }
        }

        private int _age = 0;

        public int Age
        {
            get { retuenter code heren _age; }
            set
            {
                _age = value;
                RaisePropertyChangedEvent("Age");
            }
        }


        #endregion
    }
    }

提前致谢.

解决方法:

例如:Code MSDN Reference Data Annotations

在模型类中添加引用:

using System.ComponentModel.DataAnnotations;

然后只需以下属性.

[Required(ErrorMessage = "Email address is required")] 
[EmailAddress(ErrorMessage = "Email Address is Invalid")] 
public string Email 
{ 
    get { return GetValue(() => Email); } 
    set { SetValue(() => Email, value); } 
}

更新完整示例:
您的类应使用基类PropertyChangedNotification
创建clas PropertyChangedNotification,如下所示(在链接的页面中,您可以找到它)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;

namespace EmployeeApp.Notification
{
   public abstract class PropertyChangedNotification : INotifyPropertyChanged, IDataErrorInfo
   {
      #region Fields

      private readonly Dictionary<string, object> _values = new Dictionary<string, object>();

      #endregion

      #region Protected

      /// <summary>
      /// Sets the value of a property.
      /// </summary>
      /// <typeparam name="T">The type of the property value.</typeparam>
      /// <param name="propertySelector">Expression tree contains the property definition.</param>
      /// <param name="value">The property value.</param>
      protected void SetValue<T>(Expression<Func<T>> propertySelector, T value)
      {
         string propertyName = GetPropertyName(propertySelector);

         SetValue<T>(propertyName, value);
      }

      /// <summary>
      /// Sets the value of a property.
      /// </summary>
      /// <typeparam name="T">The type of the property value.</typeparam>
      /// <param name="propertyName">The name of the property.</param>
      /// <param name="value">The property value.</param>
      protected void SetValue<T>(string propertyName, T value)
      {
         if (string.IsNullOrEmpty(propertyName))
         {
            throw new ArgumentException("Invalid property name", propertyName);
         }

         _values[propertyName] = value;
         NotifyPropertyChanged(propertyName);
      }

      /// <summary>
      /// Gets the value of a property.
      /// </summary>
      /// <typeparam name="T">The type of the property value.</typeparam>
      /// <param name="propertySelector">Expression tree contains the property definition.</param>
      /// <returns>The value of the property or default value if not exist.</returns>
      protected T GetValue<T>(Expression<Func<T>> propertySelector)
      {
         string propertyName = GetPropertyName(propertySelector);

         return GetValue<T>(propertyName);
      }

      /// <summary>
      /// Gets the value of a property.
      /// </summary>
      /// <typeparam name="T">The type of the property value.</typeparam>
      /// <param name="propertyName">The name of the property.</param>
      /// <returns>The value of the property or default value if not exist.</returns>
      protected T GetValue<T>(string propertyName)
      {
         if (string.IsNullOrEmpty(propertyName))
         {
            throw new ArgumentException("Invalid property name", propertyName);
         }

         object value;
         if (!_values.TryGetValue(propertyName, out value))
         {
            value = default(T);
            _values.Add(propertyName, value);
         }

         return (T)value;
      }

      /// <summary>
      /// Validates current instance properties using Data Annotations.
      /// </summary>
      /// <param name="propertyName">This instance property to validate.</param>
      /// <returns>Relevant error string on validation failure or <see cref="System.String.Empty"/> on validation success.</returns>
      protected virtual string OnValidate(string propertyName)
      {
         if (string.IsNullOrEmpty(propertyName))
         {
            throw new ArgumentException("Invalid property name", propertyName);
         }

         string error = string.Empty;
         var value = GetValue(propertyName);
         var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(1);
         var result = Validator.TryValidateProperty(
             value,
             new ValidationContext(this, null, null)
             {
                MemberName = propertyName
             },
             results);

         if (!result)
         {
            var validationResult = results.First();
            error = validationResult.ErrorMessage;
         }

         return error;
      }

      #endregion

      #region Change Notification

      /// <summary>
      /// Raised when a property on this object has a new value.
      /// </summary>
      public event PropertyChangedEventHandler PropertyChanged;

      /// <summary>
      /// Raises this object's PropertyChanged event.
      /// </summary>
      /// <param name="propertyName">The property that has a new value.</param>
      protected void NotifyPropertyChanged(string propertyName)
      {
         this.VerifyPropertyName(propertyName);

         PropertyChangedEventHandler handler = this.PropertyChanged;
         if (handler != null)
         {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
         }
      }

      protected void NotifyPropertyChanged<T>(Expression<Func<T>> propertySelector)
      {
         var propertyChanged = PropertyChanged;
         if (propertyChanged != null)
         {
            string propertyName = GetPropertyName(propertySelector);
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
         }
      }

      #endregion // INotifyPropertyChanged Members

      #region Data Validation

      string IDataErrorInfo.Error
      {
         get
         {
            throw new NotSupportedException("IDataErrorInfo.Error is not supported, use IDataErrorInfo.this[propertyName] instead.");
         }
      }

      string IDataErrorInfo.this[string propertyName]
      {
         get
         {
            return OnValidate(propertyName);
         }
      }

      #endregion

      #region Privates

      private string GetPropertyName(LambdaExpression expression)
      {
         var memberExpression = expression.Body as MemberExpression;
         if (memberExpression == null)
         {
            throw new InvalidOperationException();
         }

         return memberExpression.Member.Name;
      }

      private object GetValue(string propertyName)
      {
         object value;
         if (!_values.TryGetValue(propertyName, out value))
         {
            var propertyDescriptor = TypeDescriptor.GetProperties(GetType()).Find(propertyName, false);
            if (propertyDescriptor == null)
            {
               throw new ArgumentException("Invalid property name", propertyName);
            }

            value = propertyDescriptor.GetValue(this);
            _values.Add(propertyName, value);
         }

         return value;
      }

      #endregion

      #region Debugging

      /// <summary>
      /// Warns the developer if this object does not have
      /// a public property with the specified name. This 
      /// method does not exist in a Release build.
      /// </summary>
      [Conditional("DEBUG")]
      [DebuggerStepThrough]
      public void VerifyPropertyName(string propertyName)
      {
         // Verify that the property name matches a real,  
         // public, instance property on this object.
         if (TypeDescriptor.GetProperties(this)[propertyName] == null)
         {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
               throw new Exception(msg);
            else
               Debug.Fail(msg);
         }
      }

      /// <summary>
      /// Returns whether an exception is thrown, or if a Debug.Fail() is used
      /// when an invalid property name is passed to the VerifyPropertyName method.
      /// The default value is false, but subclasses used by unit tests might 
      /// override this property's getter to return true.
      /// </summary>
      protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

      #endregion // Debugging Aides
   }
}

在您的视图中,您可以添加:

<Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
    <TextBox Grid.Column="0"
           Name="txtEmail" 
           Text="{Binding Email, Mode=TwoWay, 
           UpdateSourceTrigger=PropertyChanged, 
           ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Width="100">
    </TextBox>
    <TextBlock Grid.Column="1" Grid.Row="0" 
               Text="{Binding (Validation.Errors)[0].ErrorContent, ElementName=txtEmail}" 
               Foreground="Red" Margin="5,0,0,0"/>
</Grid>

关于按钮单击的验证,只需执行命令并在那里引发通知.

点击验证的更改

视图

<TextBox Grid.Column="0"
           Name="txtTestValue" Text="{Binding MyTextValue, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Width="100">
            </TextBox>
            <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding (Validation.Errors)[0].ErrorContent, ElementName=txtTestValue}" Foreground="Red" Margin="5,0,0,0"/>
<Button Content="Validate" Command="{Binding ValidationCommand}">

</Button>

模型

ValidationCommand = new RelayCommand(ExecuteMyCommand,() => true);

….

public RelayCommand ValidationCommand
{
    get;
    private set;
}

private void ExecuteMyCommand()
{
    OnValidate("MyTextValue");
}

标签:c,linq,mvvm,wpf,data-annotations
来源: https://codeday.me/bug/20190716/1476852.html