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

相关文章
相关标签/搜索