zoukankan      html  css  js  c++  java
  • WPF 自定义TextBox,可控制键盘输入内容

    非原创,整理之前的代码的时候找出来的,可用,与大家分享一下!

      1   public class NumbericBoxWithZero : NumericBox
      2     {
      3         public NumbericBoxWithZero()
      4             : base()
      5         {
      6 
      7 
      8         }
      9         protected override void SetTextAndSelection(string text)
     10         {
     11             if (text.IndexOf('.') == -1)
     12             {
     13                 text = text + ".00";
     14             }
     15             else
     16             {
     17                 if (text.IndexOf('.') != text.Length - 1)
     18                 {
     19                     string front = text.Substring(0,text.IndexOf('.'));
     20                     string back = text.Substring(text.IndexOf('.') + 1, text.Length - text.IndexOf('.') - 1);
     21                     if(back != "00")
     22                         text = string.Format("{0}.{1:d2}",front,int.Parse(back));
     23                 }
     24             }
     25             base.SetTextAndSelection(text);
     26         }
     27     }
     28     /// <summary>
     29     /// NumericBox功能设计
     30     /// 只能输入0-9的数字和至多一个小数点;
     31     ///能够屏蔽通过非正常途径的不正确输入(输入法,粘贴等);
     32     ///能够控制小数点后的最大位数,超出位数则无法继续输入;
     33     ///能够选择当小数点数位数不足时是否补0;
     34     ///去除开头部分多余的0(为方便处理,当在开头部分输入0时,自动在其后添加一个小数点);
     35     ///由于只能输入一个小数点,当在已有的小数点前再次按下小数点,能够跳过小数点;
     36     /// </summary>
     37     public class NumericBox : TextBox
     38     {
     39         #region Dependency Properties
     40         /// <summary>
     41         /// 最大小数点位数
     42         /// </summary>
     43         public int MaxFractionDigits
     44         {
     45             get { return (int)GetValue(MaxFractionDigitsProperty); }
     46             set { SetValue(MaxFractionDigitsProperty, value); }
     47         }
     48         // Using a DependencyProperty as the backing store for MaxFractionDigits.  This enables animation, styling, binding, etc...
     49         public static readonly DependencyProperty MaxFractionDigitsProperty =
     50             DependencyProperty.Register("MaxFractionDigits", typeof(int), typeof(NumericBox), new PropertyMetadata(2));
     51 
     52         /// <summary>
     53         /// 不足位数是否补零
     54         /// </summary>
     55         public bool IsPadding
     56         {
     57             get { return (bool)GetValue(IsPaddingProperty); }
     58             set { SetValue(IsPaddingProperty, value); }
     59         }
     60         // Using a DependencyProperty as the backing store for IsPadding.  This enables animation, styling, binding, etc...
     61         public static readonly DependencyProperty IsPaddingProperty =
     62             DependencyProperty.Register("IsPadding", typeof(bool), typeof(NumericBox), new PropertyMetadata(true));
     63 
     64         #endregion
     65 
     66         public NumericBox()
     67         {
     68             TextBoxFilterBehavior behavior = new TextBoxFilterBehavior();
     69             behavior.TextBoxFilterOptions = TextBoxFilterOptions.Numeric | TextBoxFilterOptions.Dot;
     70             Interaction.GetBehaviors(this).Add(behavior);
     71             this.TextChanged += new TextChangedEventHandler(NumericBox_TextChanged);
     72         }
     73 
     74         /// <summary>
     75         /// 设置Text文本以及光标位置
     76         /// </summary>
     77         /// <param name="text"></param>
     78         protected virtual void SetTextAndSelection(string text)
     79         {
     80             //保存光标位置
     81             int selectionIndex = this.SelectionStart;
     82             this.Text = text;
     83             //恢复光标位置 系统会自动处理光标位置超出文本长度的情况
     84             this.SelectionStart = selectionIndex;
     85         }
     86 
     87         /// <summary>
     88         /// 去掉开头部分多余的0
     89         /// </summary>
     90         private void TrimZeroStart()
     91         {
     92             string resultText = this.Text;
     93             //计算开头部分0的个数
     94             int zeroCount = 0;
     95             foreach (char c in this.Text)
     96             {
     97                 if (c == '0') { zeroCount++; }
     98                 else { break; }
     99             }
    100 
    101             //当前文本中包含小数点
    102             if (this.Text.Contains('.'))
    103             {
    104                 //0后面跟的不是小数点,则删除全部的0
    105                 if (this.Text[zeroCount] != '.')
    106                 {
    107                     resultText = this.Text.TrimStart('0');
    108                 }
    109                 //否则,保留一个0
    110                 else if (zeroCount > 1)
    111                 {
    112                     resultText = this.Text.Substring(zeroCount - 1);
    113                 }
    114             }
    115             //当前文本中不包含小数点,则保留一个0,并在其后加一个小数点,并将光标设置到小数点前
    116             else if (zeroCount > 0)
    117             {
    118                 resultText = "0." + this.Text.TrimStart('0');
    119                 this.SelectionStart = 1;
    120             }
    121 
    122             SetTextAndSelection(resultText);
    123         }
    124 
    125         void NumericBox_TextChanged(object sender, TextChangedEventArgs e)
    126         {
    127             int decimalIndex = this.Text.IndexOf('.');
    128             if (decimalIndex >= 0)
    129             {
    130                 //小数点后的位数
    131                 int lengthAfterDecimal = this.Text.Length - decimalIndex - 1;
    132                 if (lengthAfterDecimal > MaxFractionDigits)
    133                 {
    134                     SetTextAndSelection(this.Text.Substring(0, this.Text.Length - (lengthAfterDecimal - MaxFractionDigits)));
    135                 }
    136                 else if (IsPadding)
    137                 {
    138                     SetTextAndSelection(this.Text.PadRight(this.Text.Length + MaxFractionDigits - lengthAfterDecimal, '0'));
    139                 }
    140             }
    141             TrimZeroStart();
    142         }
    143     }
    144     /// <summary>
    145     /// TextBox筛选行为,过滤不需要的按键
    146     /// </summary>
    147     public class TextBoxFilterBehavior : Behavior<TextBox>
    148     {
    149         private string _prevText = string.Empty;
    150         public TextBoxFilterBehavior()
    151         {
    152         }
    153         #region Dependency Properties
    154         /// <summary>
    155         /// TextBox筛选选项,这里选择的为过滤后剩下的按键
    156         /// 控制键不参与筛选,可以多选组合
    157         /// </summary>
    158         public TextBoxFilterOptions TextBoxFilterOptions
    159         {
    160             get { return (TextBoxFilterOptions)GetValue(TextBoxFilterOptionsProperty); }
    161             set { SetValue(TextBoxFilterOptionsProperty, value); }
    162         }
    163 
    164         // Using a DependencyProperty as the backing store for TextBoxFilterOptions.  This enables animation, styling, binding, etc...
    165         public static readonly DependencyProperty TextBoxFilterOptionsProperty =
    166             DependencyProperty.Register("TextBoxFilterOptions", typeof(TextBoxFilterOptions), typeof(TextBoxFilterBehavior), new PropertyMetadata(TextBoxFilterOptions.None));
    167         #endregion
    168 
    169         protected override void OnAttached()
    170         {
    171             base.OnAttached();
    172             this.AssociatedObject.KeyDown += new KeyEventHandler(AssociatedObject_KeyDown);
    173             this.AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
    174         }
    175 
    176         protected override void OnDetaching()
    177         {
    178             base.OnDetaching();
    179             this.AssociatedObject.KeyDown -= new KeyEventHandler(AssociatedObject_KeyDown);
    180             this.AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);
    181         }
    182 
    183         #region Events
    184 
    185         /// <summary>
    186         /// 处理通过其它手段进行的输入
    187         /// </summary>
    188         /// <param name="sender"></param>
    189         /// <param name="e"></param>
    190         void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
    191         {
    192             //如果符合规则,就保存下来
    193             if (IsValidText(this.AssociatedObject.Text))
    194             {
    195                 _prevText = this.AssociatedObject.Text;
    196             }
    197             //如果不符合规则,就恢复为之前保存的值
    198             else
    199             {
    200                 int selectIndex = this.AssociatedObject.SelectionStart - (this.AssociatedObject.Text.Length - _prevText.Length);
    201                 this.AssociatedObject.Text = _prevText;
    202 
    203                 if (selectIndex < 0)
    204                     selectIndex = 0;
    205 
    206                 this.AssociatedObject.SelectionStart = selectIndex;
    207             }
    208 
    209         }
    210 
    211         /// <summary>
    212         /// 处理按键产生的输入
    213         /// </summary>
    214         /// <param name="sender"></param>
    215         /// <param name="e"></param>
    216         void AssociatedObject_KeyDown(object sender, KeyEventArgs e)
    217         {
    218             bool handled = true;
    219             //不进行过滤
    220             if (TextBoxFilterOptions == TextBoxFilterOptions.None ||
    221                 KeyboardHelper.IsControlKeys(e.Key))
    222             {
    223                 handled = false;
    224             }
    225             //数字键
    226             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric))
    227             {
    228                 handled = !KeyboardHelper.IsDigit(e.Key);
    229             }
    230             //小数点
    231             //if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))
    232             //{
    233             //    handled = !(KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && !_prevText.Contains("."));
    234             //    if (KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && _prevText.Contains("."))
    235             //    {
    236             //        //如果输入位置的下一个就是小数点,则将光标跳到小数点后面
    237             //        if (this.AssociatedObject.SelectionStart< this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')
    238             //        {
    239             //            this.AssociatedObject.SelectionStart++;
    240             //        }                    
    241             //    }
    242             //}
    243             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))
    244             {
    245                 handled = !(KeyboardHelper.IsDot(e.Key) && !_prevText.Contains("."));
    246                 if (KeyboardHelper.IsDot(e.Key) && _prevText.Contains("."))
    247                 {
    248                     //如果输入位置的下一个就是小数点,则将光标跳到小数点后面
    249                     if (this.AssociatedObject.SelectionStart < this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')
    250                     {
    251                         this.AssociatedObject.SelectionStart++;
    252                     }
    253                 }
    254             }
    255             //字母
    256             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))
    257             {
    258                 handled = !KeyboardHelper.IsDot(e.Key);
    259             }
    260             e.Handled = handled;
    261         }
    262 
    263         #endregion
    264 
    265         #region Private Methods
    266         /// <summary>
    267         /// 判断是否符合规则
    268         /// </summary>
    269         /// <param name="c"></param>
    270         /// <returns></returns>
    271         private bool IsValidChar(char c)
    272         {
    273             if (TextBoxFilterOptions == TextBoxFilterOptions.None)
    274             {
    275                 return true;
    276             }
    277             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric) &&
    278                 '0' <= c && c <= '9')
    279             {
    280                 return true;
    281             }
    282             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot) &&
    283                 c == '.')
    284             {
    285                 return true;
    286             }
    287             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))
    288             {
    289                 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
    290                 {
    291                     return true;
    292                 }
    293             }
    294             return false;
    295         }
    296 
    297         /// <summary>
    298         /// 判断文本是否符合规则
    299         /// </summary>
    300         /// <param name="text"></param>
    301         /// <returns></returns>
    302         private bool IsValidText(string text)
    303         {
    304             //只能有一个小数点
    305             if (text.IndexOf('.') != text.LastIndexOf('.'))
    306             {
    307                 return false;
    308             }
    309             foreach (char c in text)
    310             {
    311                 if (!IsValidChar(c))
    312                 {
    313                     return false;
    314                 }
    315             }
    316             return true;
    317         }
    318         #endregion
    319     }
    320     /// <summary>
    321     /// TextBox筛选选项
    322     /// </summary>
    323     [Flags]
    324     public enum TextBoxFilterOptions
    325     {
    326         /// <summary>
    327         /// 不采用任何筛选
    328         /// </summary>
    329         None = 0,
    330         /// <summary>
    331         /// 数字类型不参与筛选
    332         /// </summary>
    333         Numeric = 1,
    334         /// <summary>
    335         /// 字母类型不参与筛选
    336         /// </summary>
    337         Character = 2,
    338         /// <summary>
    339         /// 小数点不参与筛选
    340         /// </summary>
    341         Dot = 4,
    342         /// <summary>
    343         /// 其它类型不参与筛选
    344         /// </summary>
    345         Other = 8
    346     }
    347 
    348     /// <summary>
    349     /// TextBox筛选选项枚举扩展方法
    350     /// </summary>
    351     public static class TextBoxFilterOptionsExtension
    352     {
    353         /// <summary>
    354         /// 在全部的选项中是否包含指定的选项
    355         /// </summary>
    356         /// <param name="allOptions">所有的选项</param>
    357         /// <param name="option">指定的选项</param>
    358         /// <returns></returns>
    359         public static bool ContainsOption(this TextBoxFilterOptions allOptions, TextBoxFilterOptions option)
    360         {
    361             return (allOptions & option) == option;
    362         }
    363     }
    364     /// <summary>
    365     /// 键盘操作帮助类
    366     /// </summary>
    367     public class KeyboardHelper
    368     {
    369         /// <summary>
    370         /// 键盘上的句号键
    371         /// </summary>
    372         public const int OemPeriod = 190;
    373 
    374         #region Fileds
    375 
    376         /// <summary>
    377         /// 控制键
    378         /// </summary>
    379         private static readonly List<Key> _controlKeys = new List<Key>
    380                                                              {
    381                                                                  Key.Back,
    382                                                                  Key.CapsLock,
    383                                                                  //Key.Ctrl,
    384                                                                  Key.Down,
    385                                                                  Key.End,
    386                                                                  Key.Enter,
    387                                                                  Key.Escape,
    388                                                                  Key.Home,
    389                                                                  Key.Insert,
    390                                                                  Key.Left,
    391                                                                  Key.PageDown,
    392                                                                  Key.PageUp,
    393                                                                  Key.Right,
    394                                                                  //Key.Shift,
    395                                                                  Key.Tab,
    396                                                                  Key.Up
    397                                                              };
    398 
    399         #endregion
    400 
    401         /// <summary>
    402         /// 是否是数字键
    403         /// </summary>
    404         /// <param name="key">按键</param>
    405         /// <returns></returns>
    406         public static bool IsDigit(Key key)
    407         {
    408             bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
    409             bool retVal;
    410             //按住shift键后,数字键并不是数字键
    411             if (key >= Key.D0 && key <= Key.D9 && !shiftKey)
    412             {
    413                 retVal = true;
    414             }
    415             else
    416             {
    417                 retVal = key >= Key.NumPad0 && key <= Key.NumPad9;
    418             }
    419             return retVal;
    420         }
    421 
    422         /// <summary>
    423         /// 是否是控制键
    424         /// </summary>
    425         /// <param name="key">按键</param>
    426         /// <returns></returns>
    427         public static bool IsControlKeys(Key key)
    428         {
    429             return _controlKeys.Contains(key);
    430         }
    431 
    432         /// <summary>
    433         /// 是否是小数点
    434         /// Silverlight中无法识别问号左边的那个小数点键
    435         /// 只能识别小键盘中的小数点
    436         /// </summary>
    437         /// <param name="key">按键</param>
    438         /// <returns></returns>
    439         public static bool IsDot(Key key)
    440         {
    441             bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
    442             bool flag = false;
    443             if (key == Key.Decimal)
    444             {
    445                 flag = true;
    446             }
    447             if (key == Key.OemPeriod && !shiftKey)
    448             {
    449                 flag = true;
    450             }
    451             return flag;
    452         }
    453 
    454         /// <summary>
    455         /// 是否是小数点
    456         /// </summary>
    457         /// <param name="key">按键</param>
    458         /// <param name="keyCode">平台相关的按键代码</param>
    459         /// <returns></returns>
    460         public static bool IsDot(Key key, int keyCode)
    461         {
    462 
    463             //return IsDot(key) || (key == Key.Unknown && keyCode == OemPeriod);
    464             return IsDot(key) || (keyCode == OemPeriod);
    465         }
    466 
    467         /// <summary>
    468         /// 是否是字母键
    469         /// </summary>
    470         /// <param name="key">按键</param>
    471         /// <returns></returns>
    472         public static bool IsCharacter(Key key)
    473         {
    474             return key >= Key.A && key <= Key.Z;
    475         }
    476     }
    View Code

    使用:

     <Controls:NumericBox Grid.Column="3" Grid.Row="11"
                                        Width="200"  Height="30" Text="{Binding old,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                        CustomTextWrapping="NoWrap" CustomTextHeight="26" CustomTextWidth="170"
                                        BgForeground="{StaticResource DialogTextBgForeground}" 
                                        CustomBorderColor="{StaticResource DialogTextBorderColor}" CustomBgColor="{StaticResource DialogTextBgColor}" >
                    <i:Interaction.Behaviors>
                        <Controls:TextBoxFilterBehavior TextBoxFilterOptions="Numeric"/>  <!--可以选择输入数字,小数点等-->
                    </i:Interaction.Behaviors>
                </Controls:NumericBox>
  • 相关阅读:
    QT资料大全
    网络协议及tcp协议详解
    QT和Java的跨平台
    QString转char *
    QT删除整个文件夹
    QT获取linux下的当前用户名
    std::map自定义类型key
    QT程序自启动
    linux下通过命令连接wifi
    Rsync实现文件的同步
  • 原文地址:https://www.cnblogs.com/xiamojinnian/p/4578920.html
Copyright © 2011-2022 走看看