• WPF 验证


    目录:

    1. ValidationRule 验证
    2. Exception 验证
    3. IDataErrorInfo 验证
    4. Custom Control 验证

    1、ValidationRule 验证

    ValidationRule:是通过ValidationRule中的的Validate方法来验证我们绑定的属性。所以我们的用法是继承ValidationRule,重写他的Validate方法。示例

    public class RequiredRule : ValidationRule
        {
            public override ValidationResult Validate(object value, CultureInfo cultureInfo)
            {
                if (value == null)
                    return new ValidationResult(false, "不能为空值!");
                if (string.IsNullOrEmpty(value.ToString()))
                    return new ValidationResult(false, "不能为空字符串!");
    
                return new ValidationResult(true, null);
            }
        }

    而XAML中需要把错误信息显示出来。

    <Window.Resources>
            <ControlTemplate x:Key="ErrorTemplate">
                <Border BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder/>
                </Border>
            </ControlTemplate>
            <Style TargetType="TextBox">
                <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}">
                </Setter>
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <StackPanel>
            <TextBlock Text="姓名"/>
            <TextBox>
                <TextBox.Text>
                    <Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                        <Binding.ValidationRules>
                            <ValidationRules:RequiredRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
            <TextBlock Text="年龄"/>
            <TextBox >
                <TextBox.Text>
                    <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                        <Binding.ValidationRules>
                            <ValidationRules:GreaterThanRule Number="10"/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
        </StackPanel>

    这样显示的错误信息就会以 ToolTip和红色边框的形式显示出来。但这边如果又在TextBox里面设置ToolTip那么就会优先选择TextBox里的,也就是Style中的ToolTip遇到错误信息是不会显示出来的,而是显示TextBox中的ToolTip。所以我们可以改善一下显示的模版来解决这个问题。

    <ControlTemplate x:Key="ErrorTemplate">
                <DockPanel LastChildFill="true">
                    <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                                ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                        <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
                        </TextBlock>
                    </Border>
                    <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                        <Border BorderBrush="red" BorderThickness="1" />
                    </AdornedElementPlaceholder>
                </DockPanel>
            </ControlTemplate>

    2、Exception 验证

    Exception :我们xaml中绑定的对象是属性。所以Exception验证,就是通过属性的改变来判断是否正常。如:

     public int Age
            {
                get { return _age; }
                set
                {
                    if (value > 200)
                    {
                        throw new Exception("年龄不能大于200");
                    }
                    _age = value;
                }
            }

    同样跑出的异常在Xaml中也要显示下。XAML同上。这种方式就会破坏POCO的设计原则。

    3、IDataErrorInfo 验证

    IDataErrorInfo:这个验证是通过我们的实体对象继承IDataErrorInfo来实现的。这里声明的this索引器来访问类的成员。

     public class BaseDataErrorInfo : IDataErrorInfo
        {
            private string _error;
    
            public string this[string columnName]
            {
                get { return GetErrorFor(columnName); }
            }
    
            public string Error
            {
                get { return _error; }
                set { _error = value; }
            }
    
            public virtual string GetErrorFor(string columnName)
            {
                return string.Empty;
            }
        }
    public class Person : BaseDataErrorInfo
        {
            public string Name { get; set; }
    
            public override string GetErrorFor(string columnName)
            {
                if (columnName == "Name")
                    if (string.IsNullOrEmpty(Name))
                        return "Name 不能为空";
    
                return base.GetErrorFor(columnName);
            }
    
        }

    XAML同上。

    4、Custom Control 验证

    这里我即不想污染实体类,又想实现一个通用的Validate。我想通过我xaml绑定的属性和它所属的控件。来显示ToolTip。

      public abstract class Validator : FrameworkElement
        {
            static Validator()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(Validator), new FrameworkPropertyMetadata(typeof(Validator)));
            }
    
            public virtual string ErrorMessage { get { return string.Empty; } }
            public abstract bool InitialValidation();
            public FrameworkElement ElementName
            {
                get { return (FrameworkElement)GetValue(ElementNameProperty); }
                set { SetValue(ElementNameProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for ElementName.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ElementNameProperty =
                DependencyProperty.Register("ElementName", typeof(FrameworkElement), typeof(Validator), new PropertyMetadata(null));
    
    
            public object Source
            {
                get { return (object)GetValue(SourceProperty); }
                set { SetValue(SourceProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty SourceProperty =
                DependencyProperty.Register("Source", typeof(object), typeof(Validator), new UIPropertyMetadata(new PropertyChangedCallback(ValidPropertyPropertyChanged)));
    
            private static void ValidPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var validator = d as Validator;
                if (validator != null)
                    validator.SetSourceFromProperty();
                if (string.IsNullOrEmpty(e.NewValue.ToString()))
                {
                    if (validator != null)
                    {
                        validator.IsValid = validator.InitialValidation();
                        if (validator.ElementName.DataContext != null)
                            validator.ShowToolTip();
                        validator.IsValid = false;
                    }
                }
            }
    
            private void ShowToolTip()
            {
                if (IsValid)
                {
                    timer = new DispatcherTimer();
                    timer.Interval = TimeSpan.FromSeconds(1.5);
                    _toolTip = new ToolTip();
                    _toolTip.StaysOpen = true;
                    _toolTip.PlacementTarget = ElementName;
                    _toolTip.Placement = PlacementMode.Right;
    
                    _toolTip.Content = ErrorMessage;
                    _toolTip.IsOpen = true;
                    timer.Tick += (sender, args) =>
                                      {
                                          _toolTip.IsOpen = false;
                                          timer.Stop();
                                      };
                    timer.Start();
                }
    
            }
            private void SetSourceFromProperty()
            {
                var expression = this.GetBindingExpression(SourceProperty);
                if (expression != null && this.ElementName == null)
                    this.SetValue(Validator.ElementNameProperty, expression.DataItem as FrameworkElement);
    
            }
    
            private ToolTip _toolTip;
            private DispatcherTimer timer;
    
            public bool IsValid { get; set; }
        }

    这是一个简单的Validate基类。提供思想。功能不完善。

    然后继承这个Validator

    public class RequiredValidator : Validator
        {
            public override string ErrorMessage { get { return "不能为空值"; } }
            public override bool InitialValidation()
            {
                if (Source == null)
                    return false;
                return string.IsNullOrEmpty(Source.ToString());
            }
        }

    这里ErrorMessage是显示错误信息。

    InitialValidation方法是我们要验证的规则。

    代码


    作者:dingli
    出处:http://www.cnblogs.com/dingli/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    基于jackson的kotlin json字符串对比器
    python之一mac安装HTMLTestRunner.py
    python之插件安装
    饿了么三面:让你怀疑人生的Spring Boot夺命连环40问
    网易三面:说说你对MySQL事务四大隔离的理解
    京东Java岗:来自面试官的夺命连环56问,你怀疑人生了吗?
    QPushButton
    宏相关使用
    C++类构造析构基础
    P8261 [CTS2022] 袜子 解题报告
  • 原文地址:https://www.cnblogs.com/dingli/p/2679076.html
Copyright © 2020-2023  润新知