C# 中实现自定义数值输入显示框,用于精准输入 / 显示数值(支持整数、浮点数、范围限制、格式控制等)
|
admin
2026年1月18日 21:11
本文热度 75
|
C# 中实现自定义数值输入显示框,用于精准输入 / 显示数值(支持整数、浮点数、范围限制、格式控制等),替代默认 TextBox 的不足,适配工控、数据录入等场景。以下是基于 WinForms 的完整实现方案,包含自定义控件核心代码、使用方法及关键特性。一、核心思路
自定义数值输入显示框的核心是继承TextBox基类(复用输入框原有交互逻辑,如光标定位、复制粘贴等),通过重写关键方法 + 封装自定义属性,实现:
- 非法输入过滤(仅允许数字、小数点、负号等合法字符)
二、完整实现代码
1. 自定义数值输入显示框(NumericInputBox.cs)
using System;using System.ComponentModel;using System.Globalization;using System.Windows.Forms;namespace CustomControls{ public class NumericInputBox : TextBox { #region 私有字段 private NumericInputType _numericType = NumericInputType.Float; private decimal _minValue = 0; private decimal _maxValue = 1000; private int _decimalPlaces = 2; private bool _allowNegative = false; private decimal _currentValue = 0; #endregion #region 公共枚举(数值类型:修改枚举名为 NumericInputType,消除冲突) public enum NumericInputType { Integer, Float } #endregion #region 公共属性(支持设计时编辑) [Description("数值类型(整数/浮点数)"), Category("自定义数值框设置")] public NumericInputType NumericType { get => _numericType; set { _numericType = value; if (value == NumericInputType.Integer) { _decimalPlaces = 0; FormatTextByCurrentConfig(); } Invalidate(); } } [Description("允许输入的最小值"), Category("自定义数值框设置")] public decimal MinValue { get => _minValue; set { _minValue = value; if (_minValue > _maxValue) { _maxValue = _minValue; } ValidateCurrentValue(); FormatTextByCurrentConfig(); } } [Description("允许输入的最大值"), Category("自定义数值框设置")] public decimal MaxValue { get => _maxValue; set { _maxValue = value; if (_maxValue < _minValue) { _minValue = _maxValue; } ValidateCurrentValue(); FormatTextByCurrentConfig(); } } [Description("保留小数位数(仅浮点数生效,取值0-8)"), Category("自定义数值框设置")] public int DecimalPlaces { get => _decimalPlaces; set { _decimalPlaces = Math.Clamp(value, 0, 8); if (_numericType == NumericInputType.Float) { FormatTextByCurrentConfig(); } Invalidate(); } } [Description("是否允许输入负数"), Category("自定义数值框设置")] public bool AllowNegative { get => _allowNegative; set { _allowNegative = value; if (!value && _minValue < 0) { _minValue = 0; } ValidateCurrentValue(); FormatTextByCurrentConfig(); } } [Description("当前输入框的数值"), Category("自定义数值框设置")] public decimal CurrentValue { get => _currentValue; set { _currentValue = Math.Clamp(value, _minValue, _maxValue); FormatTextByCurrentConfig(); } } #endregion #region 构造函数 public NumericInputBox() { this.TextAlign = HorizontalAlignment.Right; this.Text = _currentValue.ToString($"F{_decimalPlaces}"); this.DoubleBuffered = true; this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); } #endregion #region 核心重写方法:过滤非法输入 protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); if (char.IsControl(e.KeyChar)) { return; } string currentText = this.Text; int cursorPosition = this.SelectionStart; if (this.SelectionLength > 0) { currentText = currentText.Remove(cursorPosition, this.SelectionLength); } if (e.KeyChar == '-') { if (!_allowNegative || cursorPosition != 0) { e.Handled = true; return; } if (currentText.StartsWith("-")) { e.Handled = true; return; } return; } if (e.KeyChar == '.') { if (_numericType == NumericInputType.Integer || currentText.Contains(".")) { e.Handled = true; return; } return; } if (!char.IsDigit(e.KeyChar)) { e.Handled = true; } } #endregion #region 核心重写方法:失去焦点时校验并格式化数值 protected override void OnLeave(EventArgs e) { base.OnLeave(e); ValidateAndFormatInput(); } #endregion #region 私有方法:数值校验与格式化 private void ValidateAndFormatInput() { if (string.IsNullOrWhiteSpace(this.Text)) { _currentValue = _minValue; FormatTextByCurrentConfig(); return; } if (decimal.TryParse(this.Text, out decimal inputValue)) { _currentValue = Math.Clamp(inputValue, _minValue, _maxValue); } else { _currentValue = Math.Clamp(_currentValue, _minValue, _maxValue); } FormatTextByCurrentConfig(); } private void FormatTextByCurrentConfig() { if (_numericType == NumericInputType.Integer) { this.Text = ((int)_currentValue).ToString(); } else { this.Text = _currentValue.ToString($"F{_decimalPlaces}", CultureInfo.InvariantCulture); } this.SelectionStart = this.Text.Length; } private void ValidateCurrentValue() { _currentValue = Math.Clamp(_currentValue, _minValue, _maxValue); } #endregion #region 公共方法:手动刷新数值(外部调用) public void RefreshNumericValue() { ValidateAndFormatInput(); } #endregion }}
三、控件使用方法
步骤 1:添加控件到窗体
- 将上述代码放入 WinForms 项目(或编译为类库)
- 在 Visual Studio 工具箱中,右键→「选择项」→「浏览」→ 选中编译后的程序集,
NumericInputBox会出现在工具箱中 - 拖拽
NumericInputBox到窗体上,可自由调整大小
步骤 2:使用方式(设计时 + 运行时)
1. 设计时配置(可视化操作)
选中窗体上的NumericInputBox,在「属性」窗口的「自定义数值框设置」分类中,可直接配置:
- 数值类型(
NumericType):选择「Integer(整数)」或「Float(浮点数)」 - 范围限制(
MinValue/MaxValue):设置允许输入的最小 / 最大值 - 小数位数(
DecimalPlaces):浮点数类型下,设置保留的小数位数(0-8) - 是否允许负数(
AllowNegative):勾选后支持输入负数值 - 当前数值(
CurrentValue):直接设置初始显示数值
2. 运行时动态控制(代码示例)
using System;using System.Windows.Forms;using CustomControls;namespace NumericInputBoxDemo{ public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void btnSetInteger_Click(object sender, EventArgs e) { numericInputBox1.NumericType = NumericInputBox.NumericType.Integer; numericInputBox1.MinValue = 0; numericInputBox1.MaxValue = 100; numericInputBox1.AllowNegative = false; numericInputBox1.CurrentValue = 50; } private void btnSetFloat_Click(object sender, EventArgs e) { numericInputBox1.NumericType = NumericInputBox.NumericType.Float; numericInputBox1.MinValue = -100; numericInputBox1.MaxValue = 200; numericInputBox1.DecimalPlaces = 2; numericInputBox1.AllowNegative = true; numericInputBox1.CurrentValue = 36.89m; } private void btnGetValue_Click(object sender, EventArgs e) { decimal currentNum = numericInputBox1.CurrentValue; MessageBox.Show($"当前数值:{currentNum}", "数值获取", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void btnSetValue_Click(object sender, EventArgs e) { numericInputBox1.CurrentValue = 88.88m; numericInputBox1.RefreshNumericValue(); } }}
四、关键特性说明
- 核心继承:直接继承
TextBox,完全复用默认输入框的所有交互逻辑(光标操作、复制粘贴、快捷键等),无需额外封装基础功能 - 精准输入控制
- 类型过滤:仅允许整数 / 浮点数输入,自动屏蔽字母、特殊符号等非法字符
- 范围约束:通过
MinValue/MaxValue限制数值范围,超出范围自动截断到合法值 - 负数控制:通过
AllowNegative开关控制是否允许输入负号,灵活适配不同场景
- 人性化格式化
- 小数位数控制:浮点数类型下可设置 0-8 位小数,自动补零格式化
- 失去焦点自动校准:输入完成后自动校验合法性并格式化,避免无效数值
- 设计时支持:属性分类显示,可视化配置无需编写代码,降低使用门槛
- 高兼容性:支持直接绑定数据(如
BindingSource),可集成到现有 WinForms 项目中,替换默认TextBox无成本
阅读原文:原文链接
该文章在 2026/1/19 10:36:00 编辑过