你的位置:首页 > ASP.net教程

[ASP.net教程]多年前写的文本框扩展控件(有ValueChanging事件等),已放github


本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。


文章是哥(mephisto)写的,SourceLink



阅读目录

  • 介绍
  • 起因
  • 代码
  • 使用
  • GitHub

本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。


文章是哥(mephisto)写的,SourceLink



 

介绍

    这个TextBoxEx控件是cs下的,为了广大的框架都能用,就基于Framework2.0,主要有原来的textbox的功能,然后追加了EditValueChanging,数字类型输入,最大值,最小值。大家可以看完后追加下功能,比如正则输入。

起因

 

      也是5年前的事情了,当时在做cs,一般cs都会用第三方控件,比如Dev等,dev中就有很多人性化的控件,比如我们用的比较多textbox,他就有EditValueChanging事件,当时我就想,不可能所以的小项目还要用到dev,那又想自己用到这么方便的控件怎么办,于是我就开始自己做了这个控件,抛砖引玉,只是丰富了一点,但确实对我那个年代的技术提高起了些许作用。

代码

  我们先看下项目结构,因为就一个扩展控件,所以整体上看,组织结构很简单。如图:

在ControlsEx这个工程中,主要一个自定义的事件所需参数ChangingEventArgs和一个扩展控件TextBoxEx

一:ChangingEventArgs:

     主要定义EditValueChanging所需的数据结构。

 1   /// <summary> 2   /// 正在改变EventArgs 3   /// </summary> 4   public class ChangingEventArgs : CancelEventArgs 5   { 6     private object newValue; 7     private object oldValue; 8  9     /// <summary>10     /// 正在改变EventArgs11     /// </summary>12     /// <param name="oldValue">原值</param>13     /// <param name="newValue">新值</param>14     public ChangingEventArgs(object oldValue, object newValue)15       : this(oldValue, newValue, false)16     {17     }18 19     /// <summary>20     /// 正在改变EventArgs21     /// </summary>22     /// <param name="oldValue">原值</param>23     /// <param name="newValue">新值</param>24     /// <param name="cancel">是否取消</param>25     public ChangingEventArgs(object oldValue, object newValue, bool cancel)26       : base(cancel)27     {28       this.oldValue = oldValue;29       this.newValue = newValue;30     }31 32     /// <summary>33     /// 新值34     /// </summary>35     public object NewValue36     {37       get38       {39         return this.newValue;40       }41       set42       {43         this.newValue = value;44       }45     }46 47     /// <summary>48     /// 原值49     /// </summary>50     public object OldValue51     {52       get53       {54         return this.oldValue;55       }56     }57   }

View Code

二:TextBoxEx控件

     提供扩展的textbox功能。

1.委托及事件定义

     这里没有简单的用事件参数,还是使用了事件属性,大家如果感兴趣,可以去看下msdn对这两块的解释,也没用简单的使用Action,因为你设计的时候写的简单了,方便了,易用了,但是别人调用的时候就不简单,方便了。

 1     /// <summary> 2     /// 改变中事件句柄 3     /// </summary> 4     /// <param name="sender"></param> 5     /// <param name="e"></param> 6     public delegate void ChangingEventHandler(object sender, ChangingEventArgs e); 7  8     /// <summary> 9     /// <para>值改变中事件10     /// </para>11     /// </summary>12     [Description("值改变中事件"), Category("事件")]13     public event ChangingEventHandler EditValueChanging14     {15       add16       {17         base.Events.AddHandler(editValueChanging, value);18       }19       remove20       {21         base.Events.RemoveHandler(editValueChanging, value);22       }23     } 

View Code

2.设计器阶段的界面输入
     为了方便使用,就加入了设计器阶段属性,方便简单的输入。

 1     /// <summary> 2     /// 输入的最大值 3     /// </summary> 4     [Description("输入的最大值")] 5     public Int32 MaxNum 6     { 7       get { return _maxNum; } 8       set { _maxNum = value; } 9     }10     /// <summary>11     /// 输入的最小值12     /// </summary>13     [Description("输入的最小值")]14     public Int32 MinNum15     {16       get { return _minNum; }17       set18       {19         if (value <= 0)20           _minNum = value;21       }22     }23     /// <summary>24     /// 输入值类型25     /// </summary>26     [Description("输入值类型")]27     public ValueType EditValueType28     {29       get { return _editValueType; }30       set31       {32         _editValueType = value;33         //设置初始值34         if (value == ValueType.Number)35         {36           EditValue = 0;37         }38         else39           EditValue = null;40       }41     }

View Code

3.整体代码
   其实也没什么技术含量,只是提供个思路。

 1   public class TextBoxEx:TextBox 2   { 3     #region 委托 4     /// <summary> 5     /// 改变中事件句柄 6     /// </summary> 7     /// <param name="sender"></param> 8     /// <param name="e"></param> 9     public delegate void ChangingEventHandler(object sender, ChangingEventArgs e); 10     #endregion 11  12     #region 参数 13     private Int32 _maxNum = Int32.MaxValue;//最大值 14     private Int32 _minNum = Int32.MinValue;//最小值 15     private ValueType _editValueType = ValueType.String; 16     private static readonly object editValueChanging = new object();//EditValueChanging事件对应的Key 17     #endregion 18  19     #region Protected 参数 20     /// <summary> 21     /// 编制值 22     /// </summary> 23     protected object fEditValue = null; 24     /// <summary> 25     /// 编辑原始值 26     /// </summary> 27     protected object fOldEditValue = null;  28     #endregion 29  30     #region 公有属性 31     /// <summary> 32     /// 输入的最大值 33     /// </summary> 34     [Description("输入的最大值")] 35     public Int32 MaxNum 36     { 37       get { return _maxNum; } 38       set { _maxNum = value; } 39     } 40     /// <summary> 41     /// 输入的最小值 42     /// </summary> 43     [Description("输入的最小值")] 44     public Int32 MinNum 45     { 46       get { return _minNum; } 47       set 48       { 49         if (value <= 0) 50           _minNum = value; 51       } 52     } 53     /// <summary> 54     /// 输入值类型 55     /// </summary> 56     [Description("输入值类型")] 57     public ValueType EditValueType 58     { 59       get { return _editValueType; } 60       set 61       { 62         _editValueType = value; 63         //设置初始值 64         if (value == ValueType.Number) 65         { 66           EditValue = 0; 67         } 68         else 69           EditValue = null; 70       } 71     } 72    73     #endregion 74  75     #region 事件属性 76     /// <summary> 77     /// <para>值改变中事件 78     /// </para> 79     /// </summary> 80     [Description("值改变中事件"), Category("事件")] 81     public event ChangingEventHandler EditValueChanging 82     { 83       add 84       { 85         base.Events.AddHandler(editValueChanging, value); 86       } 87       remove 88       { 89         base.Events.RemoveHandler(editValueChanging, value); 90       } 91     }  92     #endregion 93  94     #region 私有属性 95     /// <summary> 96     /// 编辑值 97     /// </summary> 98     private object EditValue 99     {100       get { return fEditValue; }101       set102       {103         if (EditValue == value) return;104         OnEditValueChanging(new ChangingEventArgs(fEditValue, value));105         this.Text = fEditValue == null ? null : fEditValue.ToString();106       }107     }108     #endregion109 110     #region 事件111     /// <summary>112     /// 编辑值正在改变事件113     /// </summary>114     /// <param name="e"></param>115     protected virtual void OnEditValueChanging(ChangingEventArgs e)116     {117       //调用注册的事件118       ReiseEditValueChanging(e);119 120       if (e.Cancel)//注册的事件取消 还原值121       {122         fEditValue = e.OldValue;123         return;124       }125 126       switch (_editValueType)127       {128         case ValueType.Number://数值类型129           {130             if (e.NewValue != null && !string.IsNullOrEmpty(e.NewValue.ToString()))//非空值131             {132               int intNewNum = 0;133               if (!Int32.TryParse(e.NewValue.ToString(), out intNewNum))//非数字134               {135                 string strOp = e.NewValue.ToString();136                 //负号137                 if (ParseValueIsMinus(strOp))138                 {139                   strOp = strOp.Replace("-", "");140 141                   int tempMin = 0;142                   if (Int32.TryParse(strOp, out tempMin))143                   {144                     if (tempMin > Math.Abs(MinNum + 1))145                     {146                       fEditValue = e.OldValue;147                       return;148                     }149                   }150                   else151                   {152                     fEditValue = e.OldValue;153                     return;154                   }155                   strOp = "-" + strOp;156                   fEditValue = strOp;157                 }158                 else if (strOp.Contains("-"))//多负号情况159                 {160                   strOp = strOp.Replace("-", "");161                   int tempMax = 0;162                   if (Int32.TryParse(strOp, out tempMax))163                   {164                     if (tempMax > MaxNum)165                     {166                       fEditValue = e.OldValue;167                       return;168                     }169                   }170                   else171                   {172                     fEditValue = e.OldValue;173                     return;174                   }175                   fEditValue = strOp;176                 }177                 else178                   fEditValue = e.OldValue;//还原179                 return;180               }181               if (intNewNum > MaxNum182                 || intNewNum < MinNum)//不在范围里的数据183               {184                 fEditValue = e.OldValue;185                 return;186               }187               //同步设置新值188               fEditValue = e.NewValue;189             }190             else191             {192               //同步设置新值(特殊)193               fEditValue = 0;194             }195           } break;196         case ValueType.String:197           {198             fEditValue = e.NewValue;199           } break;200         default:201           {202             fEditValue = e.NewValue;203           } break;204 205       }206     }207 208     /// <summary>209     /// 值改变后事件210     /// </summary>211     /// <param name="e"></param>212     protected override void OnTextChanged(EventArgs e)213     {214       if (this.Text != null)215         this.SelectionStart = this.Text.Length;216 217       if (this.Text.Equals(EditValue))218       {219         return;220       }221 222       base.OnTextChanged(e);223       EditValue = this.Text;224     }225 226     /// <summary>227     /// 调用注册的事件228     /// </summary>229     /// <param name="e"></param>230     public void ReiseEditValueChanging(ChangingEventArgs e)231     {232       ChangingEventHandler handler = (ChangingEventHandler)this.Events[editValueChanging];233       if (handler != null) handler(this, e);234     }235     #endregion236 237     #region 内部方法238     /// <summary>239     /// 判断字符串是否是负数240     /// </summary>241     /// <param name="strOp"></param>242     /// <returns></returns>243     private bool ParseValueIsMinus(string strOp)244     {245       bool blReturn = false;246 247       int index = strOp.IndexOf('-');248       if (index >= 0)249       {250         index = strOp.IndexOf('-', index + 1);251         if (index < 0)252           blReturn = true;253       }254       return blReturn;255     }256     #endregion257 258 259     #region 枚举260     /// <summary>261     /// 改变值类型262     /// </summary>263     public enum ValueType264     {265       Number,266       String,267     } 268     #endregion269   }270 }

View Code

 

使用

由于是控件,所以没有采用UnitTest方式,而是建立一个winfrom窗体进行测试。

定义2个控件

texBoxEx1 字符串输入

tbxBoxEx2 数字型输入,最小值-200,最大值200

代码做了简单过滤

 1     private void textBoxEx1_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e) 2     { 3       //简单的过滤abc和100 4       if (e.NewValue.ToString() == "abc") 5         e.Cancel = true; 6     } 7  8     private void textBoxEx2_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e) 9     {10       //简单的过滤10011       int temp = (int)e.NewValue;12       if (temp == 100)13         e.Cancel = true;14     }

View Code

测试结果如下:

对于tbxBoxEx1的输入abc,在输入c的时候就输入不进去了,换个d就可以输入进去了。

对于tbxBoxEx2,在输入-201的时候不能输入,201的时候也不能,100的时候也不能。由于验证机制是调用订阅的验证机制然后才是基类的验证机制,所以订阅的是做扩展用的。所以订阅的代码还是要做点异常处理,比如输入其他字符号。当时想的是默认情况下基类判断起作用,如果想做扩展,订阅这个事件,然后处理,但是现在过了这多年回来看,这块还是需要优化下,应该为了更方便的点,基类的判断应该是一直前的,这样可以少了很多异常判断,所以这里测试代码就简单的过滤100就行了,负数等的自行取消订阅事件里的代码。

GitHub

https://github.com/sinodzh/ControlsEx

本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。


文章是哥(mephisto)写的,SourceLink