Accessing WPF control validation rules from code

前端 未结 3 1699
长情又很酷
长情又很酷 2021-02-01 20:36

XAML:

  
      
          
              
                  <         


        
3条回答
  •  谎友^
    谎友^ (楼主)
    2021-02-01 21:07

    Much thanks to Fredrik Hedblad for his solution. It helped me as well. I also agree with Lukáš Koten that it would best be used as a behavior. That way there's not a mix of application logic mixed in the view layer and the view-model doesn't have to worry about dubplicating validation just to simply have it there. Here's my version via behavior:

    As Fredrik Hedblad stated, first make sure any control validating has binding attribute NotifyOnValidationError="True".

    Here's the view logic... much simpler...

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    

    and then just under the Window start tag

        Height="Auto" Width="Auto">
    
        
    

    Then for the button, just bind the command like normal. We'll use basic view-model binding principles to disable it using the RelayCommand.

    And now the view model with its basic property and command

        private bool _isInvalid = false;
        public bool IsInvalid
        {
            get { return _isInvalid; }
            set { SetProperty(value, ref _isInvalid); }
        }
    
        private ICommand _okCommand;
        public ICommand OKCommand
        {
            get
            {
                if (_okCommand == null)
                {
                    _okCommand = new RelayCommand(param => OnOK(), canparam => CanOK());
                }
    
                return _okCommand;
            }
        }
    
        private void OnOK()
        {
            //  this.IsInvalid = false, so we're good... let's just close
            OnCloseRequested();
        }
    
        private bool CanOK()
        {
            return !this.IsInvalid;
        }
    

    And now, the behavior

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Interactivity;
    
    namespace UI.Behavior
    {
    public class ValidationErrorMappingBehavior : Behavior
    {
        #region Properties
    
        public static readonly DependencyProperty ValidationErrorsProperty = DependencyProperty.Register("ValidationErrors", typeof(ObservableCollection), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(new ObservableCollection()));
    
        public ObservableCollection ValidationErrors
        {
            get { return (ObservableCollection)this.GetValue(ValidationErrorsProperty); }
            set { this.SetValue(ValidationErrorsProperty, value); }
        }
    
        public static readonly DependencyProperty HasValidationErrorProperty = DependencyProperty.Register("HasValidationError", typeof(bool), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(false));
    
        public bool HasValidationError
        {
            get { return (bool)this.GetValue(HasValidationErrorProperty); }
            set { this.SetValue(HasValidationErrorProperty, value); }
        }
    
        #endregion
    
        #region Constructors
    
        public ValidationErrorMappingBehavior()
            : base()
        { }
    
        #endregion
    
        #region Events & Event Methods
    
        private void Validation_Error(object sender, ValidationErrorEventArgs e)
        {
            if (e.Action == ValidationErrorEventAction.Added)
            {
                this.ValidationErrors.Add(e.Error);
            }
            else
            {
                this.ValidationErrors.Remove(e.Error);
            }
    
            this.HasValidationError = this.ValidationErrors.Count > 0;
        }
    
        #endregion
    
        #region Support Methods
    
        protected override void OnAttached()
        {
            base.OnAttached();
            Validation.AddErrorHandler(this.AssociatedObject, Validation_Error);
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            Validation.RemoveErrorHandler(this.AssociatedObject, Validation_Error);
        }
    
        #endregion
      }
    }
    

提交回复
热议问题