WPF验证和控制TextBox样式

时间:2010-01-29 17:19:43

标签: wpf validation textbox

我使用基于属性的验证为WPF构建了自己的自定义验证框架。我坚持最后一步是突出显示TextBox。实际上,它确实突出显示了文本框,但所有文本框都依赖于单个属性HasError。

public class RegistrationViewModel  : ViewModel
    {
        [NotNullOrEmpty("FirstName should not be null or empty")] 
        public string FirstName { get; set; }

        [NotNullOrEmpty("Middle Name is required!")]
        public string MiddleName { get; set; } 

        [NotNullOrEmpty("LastName should not be null or empty")] 
        public string LastName { get; set; }

        public bool HasError
        {
            get
            {
                **return Errors.Count > 0; // THIS IS THE PROBLEM** 
            }
        }

    }

这是XAML代码:

 <Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">                   

            <Style.Triggers>

                <DataTrigger Binding="{Binding Path=HasError}" Value="True">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>

            </Style.Triggers>

        </Style>

上面代码的问题在于它会突出显示所有使用“textBoxStyle”的文本框,即使它们是有效的。这是因为HasError不会基于个别属性进行验证,而是整体验证。

有什么想法吗?

更新1:

ViewModel包含Errors集合:

 public class ViewModel : ContentControl, INotifyPropertyChanged
    {
        public static DependencyProperty ErrorsProperty; 

        static ViewModel()
        {
            ErrorsProperty = DependencyProperty.Register("Errors", typeof(ObservableCollection<BrokenRule>), typeof(ViewModel)); 
        }

        public ObservableCollection<BrokenRule> Errors
        {
            get { return (ObservableCollection<BrokenRule>)GetValue(ErrorsProperty); }
            set 
            { 
                SetValue(ErrorsProperty,value);
                OnPropertyChanged("HasError");
             }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

    }

更新2:

我的验证引擎:

public bool Validate(object viewModel)
        {
            _brokenRules = new List<BrokenRule>();

            // get all the properties 

            var properties = viewModel.GetType().GetProperties(); 

            foreach(var property in properties)
            {
                // get the custom attribute 

                var attribues = property.GetCustomAttributes(typeof (EStudyValidationAttribute), false); 

                foreach(EStudyValidationAttribute att in attribues)
                {
                    bool isValid = att.IsValid(property.GetValue(viewModel,null));

                    if(isValid) continue; 

                    // add the broken rule 

                    var brokenRule = new BrokenRule()
                                         {
                                             PropertyName = property.Name,
                                             Message = att.Message
                                         }; 

                    _brokenRules.Add(brokenRule);
                }

            }

            var list = _brokenRules.ToObservableCollection(); 

            viewModel.GetType().GetProperty("Errors").SetValue(viewModel,list,null);

            return (_brokenRules.Count() == 0); 
        }

2 个答案:

答案 0 :(得分:6)

您可以在ViewModel中实现IDataErrorInfo接口,并在XAML中检查带有验证错误的控件元素的附加属性Validation.HasError;它更好,因为它是.Net中的标准机制。

<Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">                   

            <Style.Triggers>

                <DataTrigger Binding="{Binding Path=Validation.HasError}" Value="True">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>

            </Style.Triggers>

        </Style>

在TextBoxes中绑定属性时,需要将ValidatesOnDataError绑定属性设置为true。

<TextBox x:Name="someTextBox" Text="{Binding Path=someProperty, ValidatesOnDataErrors=True}">



public class ViewModel : ContentControl, INotifyPropertyChanged,IDataErrorInfo
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        public string this[string propertyName]
        {
            get
            {
                return ValidateProperty(this,propertyName);
            }
        }

        public string Error
        {
            get
            {
                            return "";
            }
        }

    }

您甚至可以使用已实施的验证方法,但请按属性检查验证。

答案 1 :(得分:0)

您可能对 WPF Application Framework (WAF) 和示例应用 BookLibrary EmailClient 感兴趣。他们使用DataAnnotations命名空间中的验证属性以及 IDataErrorInfo 接口。在验证的类中只需要另外两行代码来完成这项工作(例如BookLibrary.Domain / Book.cs)。