mephisto’blog

二人行,也有吾师!
Fork me on GitHub

多年前写的文本框扩展控件(有ValueChanging事件等),已放github

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

文章是哥(mephisto)写的,SourceLink

阅读目录

本文版权归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         /// 正在改变EventArgs
11         /// </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         /// 正在改变EventArgs
21         /// </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 NewValue
36         {
37             get
38             {
39                 return this.newValue;
40             }
41             set
42             {
43                 this.newValue = value;
44             }
45         }
46 
47         /// <summary>
48         /// 原值
49         /// </summary>
50         public object OldValue
51         {
52             get
53             {
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 EditValueChanging
14         {
15             add
16             {
17                 base.Events.AddHandler(editValueChanging, value);
18             }
19             remove
20             {
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 MinNum
15         {
16             get { return _minNum; }
17             set
18             {
19                 if (value <= 0)
20                     _minNum = value;
21             }
22         }
23         /// <summary>
24         /// 输入值类型
25         /// </summary>
26         [Description("输入值类型")]
27         public ValueType EditValueType
28         {
29             get { return _editValueType; }
30             set
31             {
32                 _editValueType = value;
33                 //设置初始值
34                 if (value == ValueType.Number)
35                 {
36                     EditValue = 0;
37                 }
38                 else
39                     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             set
102             {
103                 if (EditValue == value) return;
104                 OnEditValueChanging(new ChangingEventArgs(fEditValue, value));
105                 this.Text = fEditValue == null ? null : fEditValue.ToString();
106             }
107         }
108         #endregion
109 
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                                     else
151                                     {
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                                     else
171                                     {
172                                         fEditValue = e.OldValue;
173                                         return;
174                                     }
175                                     fEditValue = strOp;
176                                 }
177                                 else
178                                     fEditValue = e.OldValue;//还原
179                                 return;
180                             }
181                             if (intNewNum > MaxNum
182                                 || intNewNum < MinNum)//不在范围里的数据
183                             {
184                                 fEditValue = e.OldValue;
185                                 return;
186                             }
187                             //同步设置新值
188                             fEditValue = e.NewValue;
189                         }
190                         else
191                         {
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         #endregion
236 
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         #endregion
257 
258 
259         #region 枚举
260         /// <summary>
261         /// 改变值类型
262         /// </summary>
263         public enum ValueType
264         {
265             Number,
266             String,
267         } 
268         #endregion
269     }
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             //简单的过滤100
11             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

 

posted @ 2015-03-23 13:33  sinodzh  阅读(1728)  评论(7编辑  收藏  举报