wpf表单验证

在做表单的,需要对User提交数据做验证,wpf与silverlight 都提供自带的验证机制,但是只是验证,并不能在提交时提供详细的信息,此时可使用 依赖属性将错误信息整合进自定义错误集合中,即可在提交时获取相应错误信息方便后续业务处理。

Silverlifgt版本:

public class ValidationScope
    {
        public FrameworkElement ScopeElement { get; private set; }

        private readonly ObservableCollection<ValidationError> _errors = new ObservableCollection<ValidationError>();

        public ObservableCollection<ValidationError> Errors
        {
            get { return _errors; }
        }

        public bool IsValid()
        {
            return _errors.Count == 0;
        }

        public static string GetValidateBoundProperty(DependencyObject obj)
        {
            return (string)obj.GetValue(ValidateBoundPropertyProperty);
        }

        public static void SetValidateBoundProperty(DependencyObject obj, string value)
        {
            obj.SetValue(ValidateBoundPropertyProperty, value);
        }

        public static readonly DependencyProperty ValidateBoundPropertyProperty =
            DependencyProperty.RegisterAttached("ValidateBoundProperty", typeof(string), typeof(ValidationScope), new PropertyMetadata(null));

        public static ValidationScope GetValidationScope(DependencyObject obj)
        {
            return (ValidationScope)obj.GetValue(ValidationScopeProperty);
        }

        public static void SetValidationScope(DependencyObject obj, ValidationScope value)
        {
            obj.SetValue(ValidationScopeProperty, value);
        }

        public static readonly DependencyProperty ValidationScopeProperty =
            DependencyProperty.RegisterAttached("ValidationScope", typeof(ValidationScope), typeof(ValidationScope), new PropertyMetadata(null, ValidationScopeChanged));

        private static void ValidationScopeChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
        {
            ValidationScope oldScope = args.OldValue as ValidationScope;
            if (oldScope != null)
            {
                oldScope.ScopeElement.BindingValidationError -= oldScope.ScopeElement_BindingValidationError;
                oldScope.ScopeElement = null;
            }

            FrameworkElement scopeElement = source as FrameworkElement;
            if (scopeElement == null)
            {
                throw new ArgumentException(string.Format(
                    "'{0}' is not a valid type.ValidationScope attached property can only be specified on types inheriting from FrameworkElement.",
                    source));
            }

            ValidationScope newScope = (ValidationScope)args.NewValue;
            newScope.ScopeElement = scopeElement;
            newScope.ScopeElement.BindingValidationError += newScope.ScopeElement_BindingValidationError;
        }

        private void ScopeElement_BindingValidationError(object sender, ValidationErrorEventArgs e)
        {
            if (e.Action == ValidationErrorEventAction.Removed)
            {
                Errors.Remove(e.Error);
            }
            else if (e.Action == ValidationErrorEventAction.Added)
            {
                Errors.Add(e.Error);
            }
        }

        public void ValidateScope()
        {
            ForEachElement(ScopeElement, delegate(DependencyObject obj)
            {               
                string propertyName = GetValidateBoundProperty(obj);
                if (!string.IsNullOrEmpty(propertyName))
                {
                    FrameworkElement element = (FrameworkElement)obj;
                    var field = element.GetType().GetFields(BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public)
                        .Where(p => p.FieldType == typeof(DependencyProperty) && p.Name == (propertyName + "Property"))
                        .FirstOrDefault();

                    if (field == null)
                    {
                        throw new ArgumentException(string.Format(
                            "Dependency property '{0}' could not be found on type '{1}'; ValidationScope.ValidateBoundProperty",
                            propertyName, element.GetType()));
                    }
                    var be = element.GetBindingExpression((DependencyProperty)field.GetValue(null));
                    be.UpdateSource();
                }
            });
        }

        private static void ForEachElement(DependencyObject root, Action<DependencyObject> action)
        {
            int childCount = VisualTreeHelper.GetChildrenCount(root);
            for (int i = 0; i < childCount; i++)
            {
                var obj = VisualTreeHelper.GetChild(root, i);
                action(obj);
                ForEachElement(obj, action);
            }
        }
    }

  WPF版:

 public class ValidationScope 
    {
        public FrameworkElement ScopeElement { get; private set; }

        private readonly ObservableCollection<ValidationError> _errors = new ObservableCollection<ValidationError>();

        public ObservableCollection<ValidationError> Errors
        {
            get { return _errors; }
        }

        public bool IsValid()
        {
            return _errors.Count == 0;
        }

        public static string GetValidateBoundProperty(DependencyObject obj)
        {
            return (string)obj.GetValue(ValidateBoundPropertyProperty);
        }

        public static void SetValidateBoundProperty(DependencyObject obj, string value)
        {
            obj.SetValue(ValidateBoundPropertyProperty, value);
        }

        public static readonly DependencyProperty ValidateBoundPropertyProperty =
            DependencyProperty.RegisterAttached("ValidateBoundProperty", typeof(string), typeof(ValidationScope), new PropertyMetadata(null));

        public static ValidationScope GetValidationScope(DependencyObject obj)
        {
            return (ValidationScope)obj.GetValue(ValidationScopeProperty);
        }

        public static void SetValidationScope(DependencyObject obj, ValidationScope value)
        {
            obj.SetValue(ValidationScopeProperty, value);
        }

        public static readonly DependencyProperty ValidationScopeProperty =
            DependencyProperty.RegisterAttached("ValidationScope", typeof(ValidationScope), typeof(ValidationScope), new PropertyMetadata(null, ValidationScopeChanged));

        private static void ValidationScopeChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
        {
            ValidationScope oldScope = args.OldValue as ValidationScope;
            if (oldScope != null)
            {
                oldScope.ScopeElement.RemoveHandler(System.Windows.Controls.Validation.ErrorEvent, new RoutedEventHandler(oldScope.ScopeElement_BindingValidationError));
                oldScope.ScopeElement = null;
            }

            FrameworkElement scopeElement = source as FrameworkElement;
            if (scopeElement == null)
            {
                throw new ArgumentException(string.Format(
                    "'{0}' is not a valid type.ValidationScope attached property can only be specified on types inheriting from FrameworkElement.",
                    source));
            }

            ValidationScope newScope = (ValidationScope)args.NewValue;
            newScope.ScopeElement = scopeElement;
            newScope.ScopeElement.AddHandler(System.Windows.Controls.Validation.ErrorEvent, new RoutedEventHandler(newScope.ScopeElement_BindingValidationError), true);
        }

        public void ScopeElement_BindingValidationError(object sender, RoutedEventArgs e)
        {
            System.Windows.Controls.ValidationErrorEventArgs args = e as System.Windows.Controls.ValidationErrorEventArgs;

            if (args.Error.RuleInError is System.Windows.Controls.ValidationRule)
            {
                BindingExpression bindingExpression = args.Error.BindingInError as System.Windows.Data.BindingExpression;
               
                string propertyName = bindingExpression.ParentBinding.Path.Path;
                DependencyObject OriginalSource = args.OriginalSource as DependencyObject;

                string errorMessage = "";
                ReadOnlyObservableCollection<System.Windows.Controls.ValidationError> errors = System.Windows.Controls.Validation.GetErrors(OriginalSource);
                if (errors.Count > 0)
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append(propertyName).Append(":");
                    System.Windows.Controls.ValidationError error = errors[errors.Count - 1];
                    {
                        if (error.Exception == null || error.Exception.InnerException == null)
                            builder.Append(error.ErrorContent.ToString());
                        else
                            builder.Append(error.Exception.InnerException.Message);
                    }
                    errorMessage = builder.ToString();
                }

                StringBuilder errorID = new StringBuilder();
                errorID.Append(args.Error.RuleInError.ToString());
                if (args.Action == ValidationErrorEventAction.Added)
                {
                    Errors.Add(args.Error);                    
                }
                else if (args.Action == ValidationErrorEventAction.Removed)
                {
                    Errors.Remove(args.Error);
                }

            }
        }


        public void ValidateScope()
        {
            ForEachElement(ScopeElement, delegate(DependencyObject obj)
            {
                string propertyName = GetValidateBoundProperty(obj);
                if (!string.IsNullOrEmpty(propertyName))
                {
                    FrameworkElement element = (FrameworkElement)obj;
                    var field = element.GetType().GetFields(BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public)
                        .Where(p => p.FieldType == typeof(DependencyProperty) && p.Name == (propertyName + "Property"))
                        .FirstOrDefault();

                    if (field == null)
                    {
                        throw new ArgumentException(string.Format(
                            "Dependency property '{0}' could not be found on type '{1}'; ValidationScope.ValidateBoundProperty",
                            propertyName, element.GetType()));
                    }
                    var be = element.GetBindingExpression((DependencyProperty)field.GetValue(null));
                    be.UpdateSource();
                }
            });
        }

        private static void ForEachElement(DependencyObject root, Action<DependencyObject> action)
        {
            int childCount = VisualTreeHelper.GetChildrenCount(root);
            for (int i = 0; i < childCount; i++)
            {
                var obj = VisualTreeHelper.GetChild(root, i);
                action(obj);
                ForEachElement(obj, action);
            }
        }
    }

  

原文地址:https://www.cnblogs.com/CoreXin/p/5056204.html