• WPF 验证没有通过无法保存数据(非常好)+ 虚似数据库


    Validation control with a single validation rule is easy, but what if we need to validate a control using different validation rules. This article tells how to achieve multiple validation on single control in an easy and systematic way.

    Introduction

    Implementing multiple validation rules on a single control is bit difficult but not impossible. Every form has one or more controls which required to be validation on different set of logic. Since this is a very basic dependency of code that every developer has to do, this tip is dedicated only to this.

    It would be an easy task if we have set of multiple validation like required, numeric, minimum character length, folder exists, numeric range rule and we just apply one or more than one rule just by putting comma or | between the rules in our XAML file. To elaborate more, the issue lets see a situation.

    Assume one textbox control value needs to be validated with the below conditions:

    1. It has to be a required field.
    2. It has to be a numeric field.
    3. It should be between ranges of 1 to 100.

    Or:

    1. It has to be a required Field
    2. Input value should have minimum 3 characters.

    Or:

    1. It has to be a required field.
    2. Input value should be a valid directory.

    Now one way is to create a class and club all rules into one and then use that one rule, but isn't it is a time consuming job and difficult to manage at the later stage of project? Imagine how many combination of rules we will have to make and if there is any logic change, we need to go back and manage each rule with the new changes.

    Background

    Continue to my validation segment, previously I wrote a tip where I highlighted how to implement maximum length validation on controls, now I moved to other validation but with addition of how to implement multiple validation on the same control.

    Using the Code

    Would it be nice to have our XAML allow assigning these rules with some kind of separator and then XAML parser would handle this list of rules on the control.

    Well yes, this is possible and I will show you in the below steps how we can achieve this.

    Single Validation

     <TextBox x:Name="titleBox" MaxLength="100" Grid.Column="1" Margin="0,11,0,0" HorizontalAlignment="Stretch">
                <Binding
                    Path="Book.Title"
                        ValidatesOnDataErrors="True"
                         UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <rules:RequiredRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox>

    Multiple Validation

    <TextBox Text="{binding:RuleBinding Path=Book.Pages, 
            ValidationList=RequiredRule|NumericRule|RangeRule,  MinValueRange=0, MaxValueRange=999,        UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True , Mode=TwoWay}"
            Grid.Column="1" Grid.Row="6" HorizontalAlignment="Stretch"/> 

    First, we will introduce our two generic classes which would allow us to bind these multiple rules and then these rules would be set at run time.

      [MarkupExtensionReturnType(typeof(object))]
      public abstract class BindingDecoratorBase : MarkupExtension
      {
        /// <summary>
        /// The decorated binding class.
        /// 
        private Binding binding = new Binding();
     
      public override object ProvideValue(IServiceProvider provider)
        {
          //create a binding and associate it with the target
          return binding.ProvideValue(provider);
        }
     
    protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
        {
        }
    }

    Now our second class would be RuleBinding Class which will be inherited from our 1st class BindingDecoratorBase class. This class has an override of ProvideValue() method. In this method, we call the below RegisterRule() method:

    public override object ProvideValue(IServiceProvider provider)
            {
     
                //In case multiple rules are bound then it would come like "Required|Numeric
                var validationRules = ValidationList.Split(new string[] { "|", }, StringSplitOptions.RemoveEmptyEntries);
     
                foreach (var rule in validationRules)
                {
                    RegisterRule(rule);
                }
     
    
                //delegate binding creation etc. to the base class
                object val = base.ProvideValue(provider);
                return val;
            } .... 
     
    private void RegisterRule(string ruleName)
            {
                ValidationRule rule;
                switch (ruleName)
                {
                    case "RequiredRule":
                        {
                            rule = new RequiredRule();
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                    case "RangeRule":
                        {
                            rule = new MinNumericRule() 
                { MinValue = MinValueRange, MaxValue = MaxValueRange};
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                    case "NumericRule":
                        {
                            rule = new NumericRule();
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                    case "NumericNotEmpty":
                        {
                            rule = new NumericNotEmptyRule();
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                    case "FolderExistRule":
                        {
                            rule = new FolderExistRule();
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                    case "MinLengthRule":
                        {
                            rule = new MinLengthRule();
                            Binding.ValidationRules.Add(rule);
                            break;
                        }
                }
            }

    That's it, very simple implementation but very helpful and effective, when you would run this project you would find that tooltips are changing based on error for the same control.

    Points of Interest

    Working on WPF is fun and doing things in a simple way in WPF is like cherry on the cake. It is always important that we write code in a simple way so that it can be managed by other people in your absence.

    Validation plays a very important role and eliminates possibilities of all those silly errors which are enough to annoy an end user. Every minute spent to create basic structure of validation is worth it and this leads a project to an exception free successful project and saves lots of productivity.

    Hope you enjoyed reading this tip.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  • 相关阅读:
    企业——给Zabbix部署onealert云告警平台
    企业——使用API在Zabbix监控中实现查看、创建、删除监控主机的功能
    企业——监控平台Zabbix的安装
    企业——Redis的高可用的搭建
    企业——Redis的主从复制的搭建
    企业——MYSQL异步复制、半同步复制、全同步复制
    企业——memcache对PHP页面的缓存加速优化
    企业——HAproxy实现负载均衡及其常见配置
    企业——LVS 负载均衡的八种调度算法
    PHP微信公众号开发之自动回复
  • 原文地址:https://www.cnblogs.com/qq247039968/p/4066272.html
Copyright © 2020-2023  润新知