zoukankan      html  css  js  c++  java
  • WPF TextBox只能输入数字

      关于WPF TextBox只能输入数字并不是一个很难的功能,网上许多的实现方式都是通过将String类型转换为Int32类型来进行判断的,自从对了Clr Via C#这本书以后就对拆装箱操作产生了恐惧,于是就想如果不(或者是减少)通过类型转换的方式去实现会不会更好。

    先做个测试,测试一下TextBox几个关键关键事件的触发顺序:

    PreviewKeyDown > KeyDown > PreviewTextInput > TextChanged > PreviewKeyUp > KeyUp

      在上面的实践中,在PreviewKeyDownKeydown中都可以捕获到按下的键值,在PreViewTextInput中可以获取到当前输入的字符,在TextChanged里面可以获取到已经发生变化的TextBox的值和对应的Changed(e.Changes),接下来就是对应的KeyUp事件,在测试的时候还有一个TextInput的事件没有触发,不知道怎么回事,不过从字面上理解这个事件貌似也没有什么用处,TextInput事件不知道处于一个什么样的状态。

      通过上面的测试发现可以在PreviewKeyDown对用户按下的键值进行判断,代码如下:       

     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来实现,代码如下:

     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事件了。

      在很多业务需求中需要这个TextBox有个最大值和最小值,我个人的做法是在TextChanged事件中进行判断,这个就没有办法避免类型转换了,代码如下:

     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事件是否重入

      如果有什么更好的想法,欢迎指教。微笑

  • 相关阅读:
    csc一些命令简记
    Winform(C#.NET)自动更新组件的使用及部分功能实现(续)
    Winform(C#.NET)自动更新组件的使用及部分功能实现
    mssql的日期函数,如何取得当前年月日,当前时间,当前月份,当前天数,一年中第几天?
    在jexus下如何简单的配置多站点
    让asp.net和php同时在Linux上跑起来
    raspberrypi(树莓派)上安装mono和jexus,运行asp.net程序
    centos6.3与jexus5.4.4配置支持php(wordpress)
    Kaggle系列1:手把手教你用tensorflow建立卷积神经网络实现猫狗图像分类
    小记tensorflow-1:tf.nn.conv2d 函数介绍
  • 原文地址:https://www.cnblogs.com/noob/p/3515825.html
Copyright © 2011-2022 走看看