WPF TextBox只能輸入數字

  關於WPF TextBox只能輸入數字並非一個很難的功能,網上許多的實現方式都是經過將String類型轉換爲Int32類型來進行判斷的,自從對了Clr Via C#這本書之後就對拆裝箱操做產生了恐懼,因而就想若是不(或者是減小)經過類型轉換的方式去實現會不會更好。app

先作個測試,測試一下TextBox幾個關鍵關鍵事件的觸發順序:ide

PreviewKeyDown > KeyDown > PreviewTextInput > TextChanged > PreviewKeyUp > KeyUp

  在上面的實踐中,在PreviewKeyDownKeydown中均可以捕獲到按下的鍵值,在PreViewTextInput中能夠獲取到當前輸入的字符,在TextChanged裏面能夠獲取到已經發生變化的TextBox的值和對應的Changed(e.Changes),接下來就是對應的KeyUp事件,在測試的時候還有一個TextInput的事件沒有觸發,不知道怎麼回事,不過從字面上理解這個事件貌似也沒有什麼用處,TextInput事件不知道處於一個什麼樣的狀態。測試

  經過上面的測試發現能夠在PreviewKeyDown對用戶按下的鍵值進行判斷,代碼以下:       this

 1         protected override void OnPreviewKeyDown(KeyEventArgs e)
 2         {
 3             if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) ||
 4                 (e.Key >= Key.D0 && e.Key <= Key.D9) ||
 5                 e.Key == Key.Back||
 6                 e.Key==Key.Left||e.Key==Key.Right)
 7             {
 8                 if (e.KeyboardDevice.Modifiers != ModifierKeys.None)
 9                 {
10                     e.Handled = true;
11                 }
12             }
13             else
14             {
15                 e.Handled = true;
16             }
17         }

  經過代碼能夠看出在輸入時只容許按下的鍵值爲數字和Backspace,而且不能是組合鍵。這樣就實現了不經過類型轉換實現了只能輸入數字的功能,在這裏多說一點,通常這個功能還須要考慮到粘貼的問題,例如將一段內容從其餘地方粘貼到文本框內,這個能夠經過DataObject的附加事件Pasting來實現,代碼以下:spa

 1         public NumericTextBox()
 2         {
 3             DataObject.AddPastingHandler(this, Text_Pasting);
 4         }
 5 
 6         private void Text_Pasting(object sender, DataObjectPastingEventArgs e)
 7         {
 8             //禁止Pasting
 9             e.CancelCommand();
10         }

  「意外」的是因爲在PreviewKeyDown中 對組合鍵進行了判斷,因此就不須要這個Pasting事件了。code

  在不少業務需求中須要這個TextBox有個最大值和最小值,我我的的作法是在TextChanged事件中進行判斷,這個就沒有辦法避免類型轉換了,代碼以下:blog

 1         protected override void OnTextChanged(TextChangedEventArgs e)
 2         {
 3             if (_isReentry)
 4             {
 5                 SelectionStart = _index;
 6                 return;
 7             }
 8             _isReentry = true;
 9             Int32 temp = 0;
10             if (Int32.TryParse(Text, out temp))
11             {
12                 if (temp > Maximum || temp < Minimum)
13                 {
14                     temp = temp > Maximum ? Maximum : Minimum;
15                     _index = SelectionStart;
16                 }
17                 Text = temp.ToString();
18             }
19             //類型不正確或者超長會致使轉換失敗
20             else
21             {
22                 Text = Int32.MaxValue.ToString();
23             }
24             _isReentry = false;
25         }

  兩個局部變量爲:事件

1         private Int32 _index;  //光標位置
2         private bool _isReentry; //標識TextChanged事件是否重入

  若是有什麼更好的想法,歡迎指教。微笑ip

相關文章
相關標籤/搜索