多年前寫的文字框擴充套件控制元件(有ValueChanging事件等),已放github

sinodzh發表於2015-03-23

本文版權歸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

 

相關文章