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) ...
随机推荐
- Android 4.0 源代码结构
Android源码的第一级目录结构 Android/abi (abi相关代码.ABI:application binary interface,应用程序二进制接口) Android/bioni ...
- ffmpeg 音频转换: use ffmpeg convert the audio from stereo to mono without changing the video part
To convert the audio from stereo to mono without changing the video part, you can use FFmpeg: ffmpeg ...
- JSON Object(如NSDictionary,NSArray)转化为JSON格式的NSString #iOS开发
NSString *string = [self jsonObjectToJSONString:inputDataDic]; -(NSString*)jsonObjectToJSONString:(i ...
- 第1周 支路变量、元件、KCL和KVL
第1周的内容,介绍了: 电阻.独立源.受控元件等实体元器件, 电流.电压.功率等抽象名词, 端口.参考方向等分析时的概念工具, KCL.KVL两大分析定律, 解线性电路的普适方法----2B法. 引入 ...
- 04-JAVA中的类和对象
1. Foo对构造函数进行了重载,那么默认的构造函数就不会被使用,在主类中,定义对象的时候,引用构造函数,却没有参数,自然无法通过编译. 2. 当设定字段初始值在初始化块前面的时候, 很明显使用了前者 ...
- 添加了有道生词本的 chrome google翻译扩展和有道翻译扩展
在chrome发布项目,需要先花美金认证,还得要美国ID,无奈. 直接上源码,需手动导入. 原始项目源码并未开源,个人是从chrome本地文件里拿出来的,拓展来的,侵删(本来想着自已写一个,业余时间, ...
- Source Insight 3.X utf8支持插件更新
[更新内容] 修复了当UTF8文件外部改变时,SI无法检测到的bug. 实现 [下载地址] 点我 [计划] 未来(无限长)优化utf8编码检测规则,提高准确度.
- php框架制做笔记
在学习完基础之后,最好的提高方式是做一个自己的框架,因为框架会用到各个知识点,在制做过程中,复习,巩固,提高. 在框架中,因为是单入口,整个脚本运行时都存在的变量我们应该设为静态变量,这样它在每个地方 ...
- Android Studio使用JNI和NDK进行开发
想要学习一下在Android Studio中进行JNI的开发,文章挺多的,但是几乎没有一个完整的说明的,中间总是有一两步漏掉.分享技术就应该完整的让读者学会,藏着掖着不是君子所为.对于那些故意含糊过去 ...
- angular js 自定义js错误处理(Angularjs js error handler)
使用AngularJS的时候,对JS错误如何自定义处理?(比如用Google Analytics记录angularjs使用中出现的js错误) AngularJS自带一个错误处理service:$exc ...