WPF如何在代码后置中设置原生TextBox可接受的小数位数
WPF原生TextBox限制小数位数的实现方法
WPF原生TextBox没有内置的Mask属性,不过可以通过以下两种简便方式实现2位/3位小数的输入限制,适配代码后置的调用需求:
方法1:封装通用小数限制附加属性(推荐,批量场景更易用)
可以先在项目里新增一个静态辅助类,封装附加属性,后续任意TextBox都可以在代码后置直接调用设置位数:
public static class TextBoxDecimalExtension { // 注册附加属性:允许的小数位数,-1表示不限制 public static readonly DependencyProperty DecimalPlacesProperty = DependencyProperty.RegisterAttached( "DecimalPlaces", typeof(int), typeof(TextBoxDecimalExtension), new PropertyMetadata(-1, OnDecimalPlacesChanged)); public static int GetDecimalPlaces(DependencyObject obj) { return (int)obj.GetValue(DecimalPlacesProperty); } public static void SetDecimalPlaces(DependencyObject obj, int value) { obj.SetValue(DecimalPlacesProperty, value); } private static void OnDecimalPlacesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not TextBox textBox) return; textBox.PreviewTextInput -= TextBox_PreviewTextInput; textBox.PreviewKeyDown -= TextBox_PreviewKeyDown; DataObject.RemovePastingHandler(textBox, OnPaste); var places = (int)e.NewValue; if (places < 0) return; textBox.PreviewTextInput += TextBox_PreviewTextInput; textBox.PreviewKeyDown += TextBox_PreviewKeyDown; DataObject.AddPastingHandler(textBox, OnPaste); } private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = (TextBox)sender; var places = GetDecimalPlaces(textBox); var fullText = textBox.Text.Insert(textBox.SelectionStart, e.Text); e.Handled = !IsValidDecimal(fullText, places); } private static void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) { // 禁用空格输入 if (e.Key == Key.Space) e.Handled = true; } private static void OnPaste(object sender, DataObjectPastingEventArgs e) { if (!e.DataObject.GetDataPresent(typeof(string))) { e.CancelCommand(); return; } var pasteText = e.DataObject.GetData(typeof(string)) as string; var textBox = (TextBox)sender; var places = GetDecimalPlaces(textBox); var fullText = textBox.Text.Insert(textBox.SelectionStart, pasteText); if (!IsValidDecimal(fullText, places)) e.CancelCommand(); } // 校验小数格式 private static bool IsValidDecimal(string input, int decimalPlaces) { // 匹配规则:可选负号,整数部分数字,可选小数点加最多decimalPlaces位小数 var regex = new Regex($"^-?\\d*(\\.\\d{{0,{decimalPlaces}}})?$"); return regex.IsMatch(input); } }
在代码后置中调用方式和你之前用Infragistics的方式几乎一致:
// 设置允许3位小数 TextBoxDecimalExtension.SetDecimalPlaces(txtInvoiceAmount, 3); // 设置允许2位小数 TextBoxDecimalExtension.SetDecimalPlaces(txtInvoiceAmount, 2);
方法2:单文本框直接加事件处理(临时小量场景适用)
如果只有少量TextBox需要限制,也可以直接在代码后置写事件:
// 窗口初始化时绑定事件 txtInvoiceAmount.PreviewTextInput += (s,e) => { var fullText = txtInvoiceAmount.Text.Insert(txtInvoiceAmount.SelectionStart, e.Text); // 2位小数就把{0,3}改成{0,2}即可 e.Handled = !Regex.IsMatch(fullText, @"^-?\d*(\.\d{0,3})?$"); }; // 额外补充粘贴拦截和空格禁用逻辑即可
两种方式都支持负数、整数输入,同时拦截非法输入和粘贴的非法内容,完全覆盖你之前的Mask功能需求。
内容的提问来源于stack exchange,提问作者krishna
相关产品推荐
相关产品推荐

