WPF 自定义TextBox,可控制键盘输入内容
非原创,整理之前的代码的时候找出来的,可用,与大家分享一下!
- public class NumbericBoxWithZero : NumericBox
- {
- public NumbericBoxWithZero()
- : base()
- {
- }
- protected override void SetTextAndSelection(string text)
- {
- if (text.IndexOf('.') == -)
- {
- text = text + ".00";
- }
- else
- {
- if (text.IndexOf('.') != text.Length - )
- {
- string front = text.Substring(,text.IndexOf('.'));
- string back = text.Substring(text.IndexOf('.') + , text.Length - text.IndexOf('.') - );
- if(back != "")
- text = string.Format("{0}.{1:d2}",front,int.Parse(back));
- }
- }
- base.SetTextAndSelection(text);
- }
- }
- /// <summary>
- /// NumericBox功能设计
- /// 只能输入0-9的数字和至多一个小数点;
- ///能够屏蔽通过非正常途径的不正确输入(输入法,粘贴等);
- ///能够控制小数点后的最大位数,超出位数则无法继续输入;
- ///能够选择当小数点数位数不足时是否补0;
- ///去除开头部分多余的0(为方便处理,当在开头部分输入0时,自动在其后添加一个小数点);
- ///由于只能输入一个小数点,当在已有的小数点前再次按下小数点,能够跳过小数点;
- /// </summary>
- public class NumericBox : TextBox
- {
- #region Dependency Properties
- /// <summary>
- /// 最大小数点位数
- /// </summary>
- public int MaxFractionDigits
- {
- get { return (int)GetValue(MaxFractionDigitsProperty); }
- set { SetValue(MaxFractionDigitsProperty, value); }
- }
- // Using a DependencyProperty as the backing store for MaxFractionDigits. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty MaxFractionDigitsProperty =
- DependencyProperty.Register("MaxFractionDigits", typeof(int), typeof(NumericBox), new PropertyMetadata());
- /// <summary>
- /// 不足位数是否补零
- /// </summary>
- public bool IsPadding
- {
- get { return (bool)GetValue(IsPaddingProperty); }
- set { SetValue(IsPaddingProperty, value); }
- }
- // Using a DependencyProperty as the backing store for IsPadding. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty IsPaddingProperty =
- DependencyProperty.Register("IsPadding", typeof(bool), typeof(NumericBox), new PropertyMetadata(true));
- #endregion
- public NumericBox()
- {
- TextBoxFilterBehavior behavior = new TextBoxFilterBehavior();
- behavior.TextBoxFilterOptions = TextBoxFilterOptions.Numeric | TextBoxFilterOptions.Dot;
- Interaction.GetBehaviors(this).Add(behavior);
- this.TextChanged += new TextChangedEventHandler(NumericBox_TextChanged);
- }
- /// <summary>
- /// 设置Text文本以及光标位置
- /// </summary>
- /// <param name="text"></param>
- protected virtual void SetTextAndSelection(string text)
- {
- //保存光标位置
- int selectionIndex = this.SelectionStart;
- this.Text = text;
- //恢复光标位置 系统会自动处理光标位置超出文本长度的情况
- this.SelectionStart = selectionIndex;
- }
- /// <summary>
- /// 去掉开头部分多余的0
- /// </summary>
- private void TrimZeroStart()
- {
- string resultText = this.Text;
- //计算开头部分0的个数
- int zeroCount = ;
- foreach (char c in this.Text)
- {
- if (c == '') { zeroCount++; }
- else { break; }
- }
- //当前文本中包含小数点
- if (this.Text.Contains('.'))
- {
- //0后面跟的不是小数点,则删除全部的0
- if (this.Text[zeroCount] != '.')
- {
- resultText = this.Text.TrimStart('');
- }
- //否则,保留一个0
- else if (zeroCount > )
- {
- resultText = this.Text.Substring(zeroCount - );
- }
- }
- //当前文本中不包含小数点,则保留一个0,并在其后加一个小数点,并将光标设置到小数点前
- else if (zeroCount > )
- {
- resultText = "0." + this.Text.TrimStart('');
- this.SelectionStart = ;
- }
- SetTextAndSelection(resultText);
- }
- void NumericBox_TextChanged(object sender, TextChangedEventArgs e)
- {
- int decimalIndex = this.Text.IndexOf('.');
- if (decimalIndex >= )
- {
- //小数点后的位数
- int lengthAfterDecimal = this.Text.Length - decimalIndex - ;
- if (lengthAfterDecimal > MaxFractionDigits)
- {
- SetTextAndSelection(this.Text.Substring(, this.Text.Length - (lengthAfterDecimal - MaxFractionDigits)));
- }
- else if (IsPadding)
- {
- SetTextAndSelection(this.Text.PadRight(this.Text.Length + MaxFractionDigits - lengthAfterDecimal, ''));
- }
- }
- TrimZeroStart();
- }
- }
- /// <summary>
- /// TextBox筛选行为,过滤不需要的按键
- /// </summary>
- public class TextBoxFilterBehavior : Behavior<TextBox>
- {
- private string _prevText = string.Empty;
- public TextBoxFilterBehavior()
- {
- }
- #region Dependency Properties
- /// <summary>
- /// TextBox筛选选项,这里选择的为过滤后剩下的按键
- /// 控制键不参与筛选,可以多选组合
- /// </summary>
- public TextBoxFilterOptions TextBoxFilterOptions
- {
- get { return (TextBoxFilterOptions)GetValue(TextBoxFilterOptionsProperty); }
- set { SetValue(TextBoxFilterOptionsProperty, value); }
- }
- // Using a DependencyProperty as the backing store for TextBoxFilterOptions. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty TextBoxFilterOptionsProperty =
- DependencyProperty.Register("TextBoxFilterOptions", typeof(TextBoxFilterOptions), typeof(TextBoxFilterBehavior), new PropertyMetadata(TextBoxFilterOptions.None));
- #endregion
- protected override void OnAttached()
- {
- base.OnAttached();
- this.AssociatedObject.KeyDown += new KeyEventHandler(AssociatedObject_KeyDown);
- this.AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
- }
- protected override void OnDetaching()
- {
- base.OnDetaching();
- this.AssociatedObject.KeyDown -= new KeyEventHandler(AssociatedObject_KeyDown);
- this.AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);
- }
- #region Events
- /// <summary>
- /// 处理通过其它手段进行的输入
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
- {
- //如果符合规则,就保存下来
- if (IsValidText(this.AssociatedObject.Text))
- {
- _prevText = this.AssociatedObject.Text;
- }
- //如果不符合规则,就恢复为之前保存的值
- else
- {
- int selectIndex = this.AssociatedObject.SelectionStart - (this.AssociatedObject.Text.Length - _prevText.Length);
- this.AssociatedObject.Text = _prevText;
- if (selectIndex < )
- selectIndex = ;
- this.AssociatedObject.SelectionStart = selectIndex;
- }
- }
- /// <summary>
- /// 处理按键产生的输入
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- void AssociatedObject_KeyDown(object sender, KeyEventArgs e)
- {
- bool handled = true;
- //不进行过滤
- if (TextBoxFilterOptions == TextBoxFilterOptions.None ||
- KeyboardHelper.IsControlKeys(e.Key))
- {
- handled = false;
- }
- //数字键
- if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric))
- {
- handled = !KeyboardHelper.IsDigit(e.Key);
- }
- //小数点
- //if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))
- //{
- // handled = !(KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && !_prevText.Contains("."));
- // if (KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && _prevText.Contains("."))
- // {
- // //如果输入位置的下一个就是小数点,则将光标跳到小数点后面
- // if (this.AssociatedObject.SelectionStart< this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')
- // {
- // this.AssociatedObject.SelectionStart++;
- // }
- // }
- //}
- if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))
- {
- handled = !(KeyboardHelper.IsDot(e.Key) && !_prevText.Contains("."));
- if (KeyboardHelper.IsDot(e.Key) && _prevText.Contains("."))
- {
- //如果输入位置的下一个就是小数点,则将光标跳到小数点后面
- if (this.AssociatedObject.SelectionStart < this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')
- {
- this.AssociatedObject.SelectionStart++;
- }
- }
- }
- //字母
- if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))
- {
- handled = !KeyboardHelper.IsDot(e.Key);
- }
- e.Handled = handled;
- }
- #endregion
- #region Private Methods
- /// <summary>
- /// 判断是否符合规则
- /// </summary>
- /// <param name="c"></param>
- /// <returns></returns>
- private bool IsValidChar(char c)
- {
- if (TextBoxFilterOptions == TextBoxFilterOptions.None)
- {
- return true;
- }
- else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric) &&
- '' <= c && c <= '')
- {
- return true;
- }
- else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot) &&
- c == '.')
- {
- return true;
- }
- else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))
- {
- if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 判断文本是否符合规则
- /// </summary>
- /// <param name="text"></param>
- /// <returns></returns>
- private bool IsValidText(string text)
- {
- //只能有一个小数点
- if (text.IndexOf('.') != text.LastIndexOf('.'))
- {
- return false;
- }
- foreach (char c in text)
- {
- if (!IsValidChar(c))
- {
- return false;
- }
- }
- return true;
- }
- #endregion
- }
- /// <summary>
- /// TextBox筛选选项
- /// </summary>
- [Flags]
- public enum TextBoxFilterOptions
- {
- /// <summary>
- /// 不采用任何筛选
- /// </summary>
- None = ,
- /// <summary>
- /// 数字类型不参与筛选
- /// </summary>
- Numeric = ,
- /// <summary>
- /// 字母类型不参与筛选
- /// </summary>
- Character = ,
- /// <summary>
- /// 小数点不参与筛选
- /// </summary>
- Dot = ,
- /// <summary>
- /// 其它类型不参与筛选
- /// </summary>
- Other =
- }
- /// <summary>
- /// TextBox筛选选项枚举扩展方法
- /// </summary>
- public static class TextBoxFilterOptionsExtension
- {
- /// <summary>
- /// 在全部的选项中是否包含指定的选项
- /// </summary>
- /// <param name="allOptions">所有的选项</param>
- /// <param name="option">指定的选项</param>
- /// <returns></returns>
- public static bool ContainsOption(this TextBoxFilterOptions allOptions, TextBoxFilterOptions option)
- {
- return (allOptions & option) == option;
- }
- }
- /// <summary>
- /// 键盘操作帮助类
- /// </summary>
- public class KeyboardHelper
- {
- /// <summary>
- /// 键盘上的句号键
- /// </summary>
- public const int OemPeriod = ;
- #region Fileds
- /// <summary>
- /// 控制键
- /// </summary>
- private static readonly List<Key> _controlKeys = new List<Key>
- {
- Key.Back,
- Key.CapsLock,
- //Key.Ctrl,
- Key.Down,
- Key.End,
- Key.Enter,
- Key.Escape,
- Key.Home,
- Key.Insert,
- Key.Left,
- Key.PageDown,
- Key.PageUp,
- Key.Right,
- //Key.Shift,
- Key.Tab,
- Key.Up
- };
- #endregion
- /// <summary>
- /// 是否是数字键
- /// </summary>
- /// <param name="key">按键</param>
- /// <returns></returns>
- public static bool IsDigit(Key key)
- {
- bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != ;
- bool retVal;
- //按住shift键后,数字键并不是数字键
- if (key >= Key.D0 && key <= Key.D9 && !shiftKey)
- {
- retVal = true;
- }
- else
- {
- retVal = key >= Key.NumPad0 && key <= Key.NumPad9;
- }
- return retVal;
- }
- /// <summary>
- /// 是否是控制键
- /// </summary>
- /// <param name="key">按键</param>
- /// <returns></returns>
- public static bool IsControlKeys(Key key)
- {
- return _controlKeys.Contains(key);
- }
- /// <summary>
- /// 是否是小数点
- /// Silverlight中无法识别问号左边的那个小数点键
- /// 只能识别小键盘中的小数点
- /// </summary>
- /// <param name="key">按键</param>
- /// <returns></returns>
- public static bool IsDot(Key key)
- {
- bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != ;
- bool flag = false;
- if (key == Key.Decimal)
- {
- flag = true;
- }
- if (key == Key.OemPeriod && !shiftKey)
- {
- flag = true;
- }
- return flag;
- }
- /// <summary>
- /// 是否是小数点
- /// </summary>
- /// <param name="key">按键</param>
- /// <param name="keyCode">平台相关的按键代码</param>
- /// <returns></returns>
- public static bool IsDot(Key key, int keyCode)
- {
- //return IsDot(key) || (key == Key.Unknown && keyCode == OemPeriod);
- return IsDot(key) || (keyCode == OemPeriod);
- }
- /// <summary>
- /// 是否是字母键
- /// </summary>
- /// <param name="key">按键</param>
- /// <returns></returns>
- public static bool IsCharacter(Key key)
- {
- return key >= Key.A && key <= Key.Z;
- }
- }
使用:
- <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>
WPF 自定义TextBox,可控制键盘输入内容的更多相关文章
- WPF自定义TextBox及ScrollViewer
原文:WPF自定义TextBox及ScrollViewer 寒假过完,在家真心什么都做不了,可能年龄大了,再想以前那样能专心坐下来已经不行了.回来第一件事就是改了项目的一个bug,最近又新增了一个新的 ...
- 在ie9下在textbox框里面输入内容按enter键会触发按钮的事件
问题 在ie下,如果存在有button标签,如果在textbox里面输入内容,按下enter键,则会触发第一个按钮的click事件,经过测试,在IE10以及以下的都存在这个问题 原因 浏览器默认行为不 ...
- WPF 自定义TextBox带水印控件,可设置圆角
一.简单设置水印TextBox控件,废话不多说看代码: <TextBox TextWrapping="Wrap" Margin="10" Height=& ...
- WPF 中textBox实现只输入数字
刚学到 通过本方法可以使文本框只能输入或复制入数字 对于数量类输入文本框比较有用 金额类只需小改动也可实现 以TextBox txtCount为例 添加TextChanged事件 代码如下 priv ...
- WPF 自定义TextBox
1.TextBox前加图标. 效果: <TextBox Width="300" Height="30" Style="{StaticResour ...
- WPF 限制Textbox输入的内容
限制文本框TextBox的输入内容,在很多场景都有应用.举个例子,现在文本框中,只能输入0.1.2.3.4.5.6.7.8.9.“|”这11个字符. 限制输入0-9很容易实现,关键是这个“|”符号.它 ...
- Ajax实现在textbox中输入内容,动态从数据库中模糊查询显示到下拉框中
功能:在textbox中输入内容,动态从数据库模糊查询显示到下拉框中,以供选择 1.建立一aspx页面,html代码 <HTML> <HEAD> <title>We ...
- WPF中TextBox限制输入不起作用的问题
最近再用textbox做限制输入时遇到一个莫名其妙的问题: 首先看代码: <TextBox Name="txtip1" Height="40" Widt ...
- VC++6.0/MFC 自定义edit 限制输入内容 响应复制粘贴全选剪切的功能
Ctrl组合键ASCII码 ^Z代表Ctrl+z ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符0(00) ...
随机推荐
- 【python】函数之内置函数
Python基础 内置函数 今天来介绍一下Python解释器包含的一系列的内置函数,下面表格按字母顺序列出了内置函数: 下面就一一介绍一下内置函数的用法: 1.abs() 返回一个数值的绝对值,可以是 ...
- [转载] Android随笔之——PackageManager详解
本文转载自: http://www.cnblogs.com/travellife/p/3932823.html 参考:http://www.cnblogs.com/xingfuzzhd/p/33745 ...
- tmux 操作
http://www.cnblogs.com/congbo/archive/2012/08/30/2649420.html https://www.digitalocean.com/community ...
- DataInputStream和DataOutputStream
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInp ...
- ZT 螨虫的话就不要跟狗多接触,狗的寄生虫很多,还有草地,
病情分析:过敏是治不好的,只能做到避免接触.指导意见:螨虫的话就不要跟狗多接触,狗的寄生虫很多,还有草地,尤其是狗经常去的地方,草地就是螨虫的传播介质.你是过敏性体质除了被免 过敏性源外,还要增强体质 ...
- I/O复用
1.I/O模型 一个输入操作通常包括两个不同阶段:等待数据准备好:从内核到进程拷贝数据. 阻塞I/O模型 非阻塞I/O模型 I/O复用模型:内核发现进程指定的一个或多个I/O条件就绪,它就通知进程,由 ...
- 让Asp.net mvc WebAPI 支持OData协议进行分页查询操作
这是我在用Asp.net mvc WebAPI 支持 OData协议 做分页查询服务时的 个人拙笔. 代码已经开发到oschina上.有兴趣的朋友可以看看,欢迎大家指出不足之处. 看过了园子里的几篇关 ...
- XE3随笔17:实例 - 模拟 Google 搜索
本例测试效果图: 代码文件: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics ...
- Ceph剖析:线程池实现
线程池ThreadPool的实现符合生产者-消费者模型,这个模型解除生产者消费者间的耦合关系,生产者可以专注处理制造产品的逻辑而不用关心产品的消费,消费者亦然.当然,生产者消费者之间需要一个连接的纽带 ...
- HTML5新增的属性
关于html5新增的属性: HTML5现在已经不是SGML的子集,主要是增加了关于图像,位置,存储,多任务等功能. 绘画CANVAS; 用于播放媒体的video和audio元素: 本地离线存储loca ...