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

Collapse | Copy Code

 <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

Collapse | Copy Code

<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.

Collapse | Copy Code

  [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:

Collapse | Copy Code

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)

时间: 2024-08-03 21:22:51

WPF 验证没有通过无法保存数据(非常好)+ 虚似数据库的相关文章

Android处理运行时变更保存数据状态恢复Activity

一.概述 运行时变更就是设备在运行时发生变化(例如屏幕旋转.键盘可用性及语言).发生这些变化,Android会重启Activity,这时就需要保存activity的状态及与activity相关的任务,以便恢复activity的状态. 为此,google提供了三种解决方案: 对于少量数据: 通过onSaveInstanceState(),保存有关应用状态的数据. 然后在 onCreate() 或 onRestoreInstanceState() 期间恢复 Activity 状态. 对于大量数据:用

hibernate4无法保存数据

hibernate4无法保存数据 author: hiu 以后都发文章我都备注一下作者了,hiu就是我了 红色字体更新日期:2014-07-08 初次使用hibernate4,使用getCurrentSession保存对象时无法将对象的数据保存进数据库,经过一番试验后,发现原来要配置事务才干保存数据. 保存数据失败原因: 没有配置事务,通过手动写一个事务,才干提交数据.手动写一个事务,用getCurrentSession也无法保存数据,仅仅能使用openSession才干保存数据. 解决的方法:

EasyUI Treegrid的使用--初始化、添加同级节点、字节节点、保存数据以及保存二进制文件

前序:该篇文章将treegrid的使用,侧重于添加节点的方法,如何保存节点到数据库.不过获取节点数据的方法有点傻.将就着,若下次还遇到使用treegrid的情况,将会好好研究一下如何更好的传递节点数据到后台.另外,文章的代码存在小问题.不过都被我用取巧的方法解决掉. 存在的问题:为什么选中根节点后,用getSelected方法,得到的是null?? 取巧的解决方法:初始化treegrid时,顺便加载onClickRow()方法,当选中一行的时候,将该行的id赋值到全局变量selectedSelf

安卓-SharedPreferences和Editor保存数据

SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)SharedPreferences常用来存储一些轻量级的数据. 在做连连看游戏的时候,需要保存游戏进度,所以稍微用了一下,这里做个小结. 我的做法是,首先给出如下定义: private SharedPreferences sp; private static String MY_APP="MYAPP"; 然后再写两个方法,执行数

android产品研发(十)--&gt;不使用静态变量保存数据

转载请标明出处:一片枫叶的专栏 上一篇文章中我们讲解了Android中的几种常见网络协议:xml,json,protobuf等,以及各自的优缺点,一般而言主要我们的App涉及到了网络传输都会有这方面的内容,具体可根据项目的需求确定各自的网络传输协议.这里可参考android产品研发(九)–>App网络传输协议 而本文讲解的其实并不是一个技术方面,而是一个android产品研发过程中的技巧:尽量不使用静态变量保存核心数据.这是为什么呢?这是因为android的进程并不是安全的,包括applicat

不要在Application保存数据

引言: 总是有需要在很多地方在你的应用程序的一些信息.它可以是一个会话,一个昂贵的计算的结果,等,它通常是很诱人的让你避免Activity之间传递对象或保持那些在持久存储的开销. 有时候建议这个模式,这将是可用在所有Activity的Application对象.这个解决方案很简单,优雅......然后这个模式是完全错误的. 如果你认为你的数据将放在那里,那么你的应用程序将最终与一个NullPointerException异常崩溃 一个简单的案例: The Application object:

Android学习笔记-保存数据的实现方法1

Android开发中,有时候我们需要对信息进行保存,那么今天就来介绍一下,保存文件到内存,以及SD卡的一些操作,及方法,供参考. 第一种,保存数据到内存中: //java开发中的保存数据的方式 public static boolean saveUserInfo(String username,String password){ File file = new File("/data/data/com.ftf.login/info.txt"); try { FileOutputStre

要清楚磁盘是如何保存数据的

成堆的有用无用的纸.杂乱无章的书籍和办公用品散落在各处,这就是我们办公桌上的一般情形.在电脑的内部,在电脑的桌面上,在"资源管理器"中,也同样充斥着无序与混乱.这种虚拟的混乱极大地影响了电脑的性能和我们办公的效率.如果数据被误删,同样会造成很大的困扰,下面就来看看该怎么办吧! 要理解如何恢复已删除的数据,首先要搞清楚磁盘如何保存数据.硬盘驱动器里面有一组盘片,数据就保存在盘片的磁道(Track)上,磁道在盘片上呈同心圆分布,读/写磁头在盘片的表面移动访问硬盘的各个区域,因此文件可以随机

android之保存偏好设置信息到shareSharedPreferences,轻量级的保存数据的方法

android之保存偏好设置信息到shareSharedPreferences,轻量级的保存数据的方法 09. 四 / android基础 / 没有评论 SharedPreferences保存数据到xml文件 有时候要保存activity的某些状态数据,就可以保存到SharedPreferences 很简单的保存和获取方法.但很实用. itcast是xml的文件名