大树下好乘凉

导航

自定义WPF常用控件(2)--输入过滤

有时候,我们需要对用户输入的信息进行处理,当用户输入了违规格式的的数据时,我们需要在后台判断,并且给出提示,但是这样一来是加重了后台的负担(尤其是B/S架构的系统或者是基于WCF服务的系统),而且一旦要对所有输入进行控制时,修改的工作量就会很大,所以我们希望能在前台进行过滤,如同ASP.NETAjax验证控件一样。

为了解决这个问题,我这里采用了重载输入控件和自定义控件结合的方式。

输入类的控件主要是TextBoxRichTextBoxPasswordBox,其中TextBoxRichTextBox的改造完全一样,因为他们可以继承,所以采用继承的方式来设计两个控件,而PasswordBox不能继承,就只能用UserControl来实现。

一、    ValidTextBoxValidRichTextBox

两者实现方法一样,这里就介绍下TextBox,首先添加用户控件,如下图

添加用户控件

添加之后,在Xmal文件中,将根节点改为由UserControl改为TextBox,如下图

改变根节点

再在后台代码文件(.   CS)文件中将继承的类改为TextBox,如下图

 

修改继承

然后实现控件的事件PreviewTextInput

/// <summary>

        /// 输入改变时,验证输入

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)

        {

            bool match = System.Text.RegularExpressions.Regex.IsMatch(e.Text, m_RegexExpression);

            e.Handled = m_IsMatchedValid ? !match : match;

            base.OnPreviewTextInput(e);

        }

事件处理中,把e.Handled设置为True,则表示事件已经处理过,调用base.OnPreviewTextInput(e);之后事件TextInput事件会触发,此时不再处理输入事件,则用户的输入不会被处理,表现在界面上就不会有任何反应,当然也可以对此事件进行丰富,我这里只是提供一个模板。如果要丰富此事件,想要在用户输入了非法字符时进行提示,则可以如此修改:

bool match = System.Text.RegularExpressions.Regex.IsMatch(e.Text, m_RegexExpression);

         e.Handled = m_IsMatchedValid ? !match : match;

if(e. Handled)

         //做点什么

         base.OnPreviewTextInput(e);

其中有两个变量,m_RegexExpression是控件需要匹配的正则表达式,默认是匹配单引号,因为很多MIS系统不能输入单引号;m_IsMatchedValid是当如果控件输入的字符匹配了正则表达式时,判定输入到底是合法还是不合法,这个变量主要用在对控件输入做匹配过滤和匹配放行时的判断,默认为false,即若匹配则不合法,需过滤。

二、    ValidPasswordBox

TextBox一样,添加用户控件,但是不再修改根节点和集成的父类(因为PasswordBoxSealed密封类,想继承都继承不了),此时在用户控件中拖入一个PasswordBox

使用用户控件

之后,添加变量m_RegexExpressionm_IsMatchedValid以及它们的对应公有属性,再实现PreviewTextInput事件,内容跟ValidTextBox完全一样。

现在讲讲ValidPassword不同的地方,由于此控件不是继承自PasswordBox,而是UserControl,所以只有UserControl的属性,如果想像PasswordBox控件一样使用其属性(比如PasswordBox有个string类型的属性Password,但是Usercontrol没有),尤其是项目已经完成了很多,在代码里都是直接使用的PasswordBox的属性,现在又想批量的改成使用ValidPasswordBox时,可能会出现部分属性提示不存在的情况,要解决这类情况,最好是在ValidPasswordBox里面建一个同名属性。举例如下:

        /// <summary>

        /// 获取或设置密码

        /// </summary>

        public string Password

        {

            get { return passwordBox.Password; }

            set { passwordBox.Password = value; }

        }

其实这个属性设置和返回的还是PasswordBox的,但整个项目中用到PasswordBox的地方,就不需要修改,只需要修改Xmal文件中的节点名称就行了。

我目前设置了PasswordMaxLength属性,大家在使用中可以自行丰富。

 

然后是样式的设置,将项目中的PasswordBox改成ValidPasswordBox之后,由于控件实质上改为了Usercontrol,所以Style也是给UserControl设置的,效果往往与之前的不同,所以要写一个样式,对应着内置的PasswordBox控件的Style

#region 提示字体样式依赖属性

 

        /// <summary>

        /// 提示字体样式依赖属性

        /// </summary>

        static readonly DependencyProperty PasswordBoxStyleProperty =

            DependencyProperty.Register(

            "PasswordBoxStyle",

            typeof(Style),

            typeof(ValidPasswordBox),

            new FrameworkPropertyMetadata(new PropertyChangedCallback(PasswordBoxStyleChangedCallback)));

 

        /// <summary>

        /// 获取或设置提示字体样式

        /// </summary>

        [Category("样式"), Description("提示字体样式")]

        public Style PasswordBoxStyle

        {

            get { return (Style)GetValue(PasswordBoxStyleProperty); }

            set { SetValue(PasswordBoxStyleProperty, value); }

        }

 

        /// <summary>

        /// 提示字体样式样式改变回调

        /// </summary>

        /// <param name="d"></param>

        /// <param name="e"></param>

        private static void PasswordBoxStyleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            ValidPasswordBox control = ((ValidPasswordBox)d);

            control.passwordBox.Style = control.PasswordBoxStyle;

        }

 

        #endregion

(关于样式属性的实现,相关说明请参见自定义WPF常用控件(1)--页码控件-四、控件样式

 

 

完整源代码下载:/Files/chenl861004/WPF控件/ValidControl.rar

 

posted on 2011-05-18 09:00  大树下好乘凉  阅读(694)  评论(0编辑  收藏  举报