Passing state of WPF ValidationRule to View Model in MVVM

前端 未结 9 1715
难免孤独
难免孤独 2021-01-01 20:10

I am stuck in a seemingly common requirement. I have a WPF Prism (for MVVM) application. My model implements the IDataErrorInfo for validation. The

9条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-01 20:56

    1. Implement IDataErrorInfo in your model or Viewmodel depending logic of binding property. You may implement in both classes.

    2. Implement this too in your base validation class. Here validation will trigger when binding IDataErrorInfo does not work.

      public virtual bool HasError
      {
          get { return _hasError; } 
          set
          {
              // if (value.Equals(_hasError)) return;
              _hasError = value;
              RaisePropertyChanged(() => HasError);
          }
      }
      
    3. Next, add global class

      public class ProtocolSettingsLayout
      {
          public static readonly DependencyProperty MVVMHasErrorProperty = DependencyProperty.RegisterAttached("MVVMHasError", typeof(bool), typeof(ProtocolSettingsLayout), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, CoerceMVVMHasError));
      
          public static bool GetMVVMHasError(DependencyObject d)
          {
              return (bool)d.GetValue(MVVMHasErrorProperty);
          }
      
          public static void SetMVVMHasError(DependencyObject d, bool value)
          {
              d.SetValue(MVVMHasErrorProperty, value);
          }
      
          private static object CoerceMVVMHasError(DependencyObject d, Object baseValue)
          {
              bool ret = (bool)baseValue;
      
              if (BindingOperations.IsDataBound(d, MVVMHasErrorProperty))
              {
                  if (GetHasErrorDescriptor(d) == null)
                  {
                      DependencyPropertyDescriptor desc = DependencyPropertyDescriptor.FromProperty(Validation.HasErrorProperty, d.GetType());
                      desc.AddValueChanged(d, OnHasErrorChanged);
                      SetHasErrorDescriptor(d, desc);
                      ret = System.Windows.Controls.Validation.GetHasError(d);
                  }
              }
              else
              {
                  if (GetHasErrorDescriptor(d) != null)
                  {
                      DependencyPropertyDescriptor desc = GetHasErrorDescriptor(d);
                      desc.RemoveValueChanged(d, OnHasErrorChanged);
                      SetHasErrorDescriptor(d, null);
                  }
              }
              return ret;
          }
      
          private static readonly DependencyProperty HasErrorDescriptorProperty = DependencyProperty.RegisterAttached("HasErrorDescriptor",
                                                                                  typeof(DependencyPropertyDescriptor),
                                                                                  typeof(ProtocolSettingsLayout));
      
          private static DependencyPropertyDescriptor GetHasErrorDescriptor(DependencyObject d)
          {
              var ret = d.GetValue(HasErrorDescriptorProperty);
              return ret as DependencyPropertyDescriptor;
          }
      
          private static void OnHasErrorChanged(object sender, EventArgs e)
          {
              DependencyObject d = sender as DependencyObject;
      
              if (d != null)
              {
                  d.SetValue(MVVMHasErrorProperty, d.GetValue(Validation.HasErrorProperty));
              }
          }
      
          private static void SetHasErrorDescriptor(DependencyObject d, DependencyPropertyDescriptor value)
          {
              var ret = d.GetValue(HasErrorDescriptorProperty);
              d.SetValue(HasErrorDescriptorProperty, value);
          }
      }
      
    4. xaml

          
      

提交回复
热议问题