Binding Validation.HasError property in MVVM

前端 未结 3 1018
南方客
南方客 2020-12-05 21:29

I am currently implementing a ValidationRule to check if some invalid character are in a TextBox. I am happy that setting the class I have implemented that inhe

3条回答
  •  天命终不由人
    2020-12-05 22:24

    In response to Anatoliy's request for an example of a non-working project:

    Generic.xaml

    
    
    
    
    

    TextBoxCustomControl.cs

    using System.Windows;
    using System.Windows.Controls;
    
    namespace TestAttachedPropertyValidationError
    {
        public class TextBoxCustomControl : Control
        {
            static TextBoxCustomControl()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxCustomControl), new FrameworkPropertyMetadata(typeof(TextBoxCustomControl)));
            }
    
            public static readonly DependencyProperty NumericPropProperty =
                DependencyProperty.Register("NumericProp", typeof (int), typeof (TextBoxCustomControl), new PropertyMetadata(default(int)));
    
            public int NumericProp
            {
                get { return (int) GetValue(NumericPropProperty); }
                set { SetValue(NumericPropProperty, value); }
            }
    
            public static readonly DependencyProperty NumericPropHasErrorProperty =
                DependencyProperty.Register("NumericPropHasError", typeof (bool), typeof (TextBoxCustomControl), new PropertyMetadata(default(bool)));
    
            public bool NumericPropHasError
            {
                get { return (bool) GetValue(NumericPropHasErrorProperty); }
                set { SetValue(NumericPropHasErrorProperty, value); }
            }
        }
    }
    

    HasErrorUtility.cs

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace TestAttachedPropertyValidationError
    {
        class HasErrorUtility
        {
            public static readonly DependencyProperty HasErrorProperty = DependencyProperty.RegisterAttached("HasError",
                                                                            typeof(bool),
                                                                            typeof(HasErrorUtility),
                                                                            new FrameworkPropertyMetadata(false,
                                                                                                          FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                                                          null,
                                                                                                          CoerceHasError));
    
            public static bool GetHasError(DependencyObject d)
            {
                return (bool)d.GetValue(HasErrorProperty);
            }
    
            public static void SetHasError(DependencyObject d, bool value)
            {
                d.SetValue(HasErrorProperty, value);
            }
    
            private static object CoerceHasError(DependencyObject d, Object baseValue)
            {
                var ret = (bool)baseValue;
                if (BindingOperations.IsDataBound(d, HasErrorProperty))
                {
                    if (GetHasErrorDescriptor(d) == null)
                    {
                        var desc = DependencyPropertyDescriptor.FromProperty(Validation.HasErrorProperty, d.GetType());
                        desc.AddValueChanged(d, OnHasErrorChanged);
                        SetHasErrorDescriptor(d, desc);
                        ret = Validation.GetHasError(d);
                    }
                }
                else
                {
                    if (GetHasErrorDescriptor(d) != null)
                    {
                        var desc = GetHasErrorDescriptor(d);
                        desc.RemoveValueChanged(d, OnHasErrorChanged);
                        SetHasErrorDescriptor(d, null);
                    }
                }
    
                return ret;
            }
    
            private static readonly DependencyProperty HasErrorDescriptorProperty = DependencyProperty.RegisterAttached("HasErrorDescriptor",
                                                                                    typeof(DependencyPropertyDescriptor),
                                                                                    typeof(HasErrorUtility));
    
            private static DependencyPropertyDescriptor GetHasErrorDescriptor(DependencyObject d)
            {
                var ret = d.GetValue(HasErrorDescriptorProperty);
                return ret as DependencyPropertyDescriptor;
            }
    
            private static void SetHasErrorDescriptor(DependencyObject d, DependencyPropertyDescriptor value)
            {
                d.SetValue(HasErrorDescriptorProperty, value);
            }
    
            private static void OnHasErrorChanged(object sender, EventArgs e)
            {
                var d = sender as DependencyObject;
    
                if (d != null)
                {
                    d.SetValue(HasErrorProperty, d.GetValue(Validation.HasErrorProperty));
                }
            }
    
        }
    }
    

    ViewModel.cs

    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    namespace TestAttachedPropertyValidationError
    {
        public class ViewModel :INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private int _vmNumericProp;
            private bool _vmNumericPropHasError;
    
            public int VmNumericProp
            {
                get { return _vmNumericProp; }
                set
                {
                    _vmNumericProp = value;
                    OnPropertyChanged();
                }
            }
    
            public bool VmNumericPropHasError
            {
                get { return _vmNumericPropHasError; }
                set
                {
                    _vmNumericPropHasError = value;
                    OnPropertyChanged();
                }
            }
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                var handler = PropertyChanged;
                if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    MainWindow.xaml

    
    
        
            
            
        
        
        
        
    

提交回复
热议问题