LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C# 中实现自定义数值输入显示框,用于精准输入 / 显示数值(支持整数、浮点数、范围限制、格式控制等)

admin
2026年1月18日 21:11 本文热度 72
C# 中实现自定义数值输入显示框,用于精准输入 / 显示数值(支持整数、浮点数、范围限制、格式控制等),替代默认 TextBox 的不足,适配工控、数据录入等场景。以下是基于 WinForms 的完整实现方案,包含自定义控件核心代码、使用方法及关键特性

一、核心思路

自定义数值输入显示框的核心是继承TextBox基类(复用输入框原有交互逻辑,如光标定位、复制粘贴等),通过重写关键方法 + 封装自定义属性,实现:

  1. 数值类型限制(整数 / 浮点数可选)
  2. 输入范围限制(最小值 / 最大值约束)
  3. 非法输入过滤(仅允许数字、小数点、负号等合法字符)
  4. 格式化显示(保留小数位数、千分位分隔等)
  5. 运行时 / 设计时灵活配置

二、完整实现代码

1. 自定义数值输入显示框(NumericInputBox.cs)

using System;using System.ComponentModel;using System.Globalization;using System.Windows.Forms;namespace CustomControls{    /// <summary>    /// 自定义数值输入显示框(已修正命名冲突问题)    /// 支持整数/浮点数、范围限制、非法输入过滤、格式化显示    /// </summary>    public class NumericInputBox : TextBox    {        #region 私有字段        // 数值类型(默认浮点数)- 注意:属性类型改为修正后的枚举名        private NumericInputType _numericType = NumericInputType.Float;        // 最小值(默认0)        private decimal _minValue = 0;        // 最大值(默认1000)        private decimal _maxValue = 1000;        // 保留小数位数(默认2位,仅浮点数生效)        private int _decimalPlaces = 2;        // 是否允许负数(默认false)        private bool _allowNegative = false;        // 当前数值        private decimal _currentValue = 0;        #endregion        #region 公共枚举(数值类型:修改枚举名为 NumericInputType,消除冲突)        /// <summary>        /// 支持的数值类型(枚举名修改,避免与属性同名)        /// </summary>        public enum NumericInputType // 关键修改:枚举名从 NumericType → NumericInputType        {            /// <summary>整数类型(Int32)</summary>            Integer,            /// <summary>浮点数类型(Decimal,高精度)</summary>            Float        }        #endregion        #region 公共属性(支持设计时编辑)        /// <summary>        /// 数值类型(整数/浮点数)- 属性名可保留 NumericType,类型改为 NumericInputType        /// </summary>        [Description("数值类型(整数/浮点数)"), Category("自定义数值框设置")]        public NumericInputType NumericType // 关键修改:属性类型从 NumericType → NumericInputType        {            get => _numericType;            set            {                _numericType = value;                // 切换为整数时,自动清空小数位数相关配置                if (value == NumericInputType.Integer) // 同步修改枚举引用                {                    _decimalPlaces = 0;                    // 格式化当前文本为整数                    FormatTextByCurrentConfig();                }                Invalidate();            }        }        /// <summary>        /// 最小值限制        /// </summary>        [Description("允许输入的最小值"), Category("自定义数值框设置")]        public decimal MinValue        {            get => _minValue;            set            {                _minValue = value;                // 确保最小值不大于最大值                if (_minValue > _maxValue)                {                    _maxValue = _minValue;                }                // 校验当前值是否超出范围                ValidateCurrentValue();                FormatTextByCurrentConfig();            }        }        /// <summary>        /// 最大值限制        /// </summary>        [Description("允许输入的最大值"), Category("自定义数值框设置")]        public decimal MaxValue        {            get => _maxValue;            set            {                _maxValue = value;                // 确保最大值不小于最小值                if (_maxValue < _minValue)                {                    _minValue = _maxValue;                }                // 校验当前值是否超出范围                ValidateCurrentValue();                FormatTextByCurrentConfig();            }        }        /// <summary>        /// 保留小数位数(仅浮点数类型生效)        /// </summary>        [Description("保留小数位数(仅浮点数生效,取值0-8)"), Category("自定义数值框设置")]        public int DecimalPlaces        {            get => _decimalPlaces;            set            {                // 限制小数位数范围0-8                _decimalPlaces = Math.Clamp(value08);                // 仅浮点数类型生效                if (_numericType == NumericInputType.Float) // 同步修改枚举引用                {                    FormatTextByCurrentConfig();                }                Invalidate();            }        }        /// <summary>        /// 是否允许输入负数        /// </summary>        [Description("是否允许输入负数"), Category("自定义数值框设置")]        public bool AllowNegative        {            get => _allowNegative;            set            {                _allowNegative = value;                // 若不允许负数,自动将最小值设为0                if (!value && _minValue < 0)                {                    _minValue = 0;                }                ValidateCurrentValue();                FormatTextByCurrentConfig();            }        }        /// <summary>        /// 当前数值(核心属性,支持直接赋值/获取)        /// </summary>        [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 核心重写方法:过滤非法输入        /// <summary>        /// 重写OnKeyPress方法,过滤非法按键输入        /// </summary>        /// <param name="e">按键事件参数</param>        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);            }            // 1. 处理负号            if (e.KeyChar == '-')            {                // 不允许负数 或 负号不在首位 → 禁止输入                if (!_allowNegative || cursorPosition != 0)                {                    e.Handled = true;                    return;                }                // 已存在负号 → 禁止重复输入                if (currentText.StartsWith("-"))                {                    e.Handled = true;                    return;                }                return;            }            // 2. 处理小数点            if (e.KeyChar == '.')            {                // 整数类型 或 已存在小数点 → 禁止输入                if (_numericType == NumericInputType.Integer || currentText.Contains(".")) // 同步修改枚举引用                {                    e.Handled = true;                    return;                }                // 负号后直接输入小数点(如-.5 → 自动补为-0.5,此处先允许输入)                return;            }            // 3. 仅允许数字字符            if (!char.IsDigit(e.KeyChar))            {                e.Handled = true;            }        }        #endregion        #region 核心重写方法:失去焦点时校验并格式化数值        /// <summary>        /// 重写OnLeave方法,失去焦点时自动校验范围+格式化显示        /// </summary>        /// <param name="e">事件参数</param>        protected override void OnLeave(EventArgs e)        {            base.OnLeave(e);            // 校验并格式化当前输入            ValidateAndFormatInput();        }        #endregion        #region 私有方法:数值校验与格式化        /// <summary>        /// 校验当前输入的数值合法性,并格式化显示        /// </summary>        private void ValidateAndFormatInput()        {            // 空文本处理:默认设为最小值            if (string.IsNullOrWhiteSpace(this.Text))            {                _currentValue = _minValue;                FormatTextByCurrentConfig();                return;            }            // 尝试转换为decimal类型            if (decimal.TryParse(this.Text, out decimal inputValue))            {                // 校验数值范围(自动截断到最小/最大值)                _currentValue = Math.Clamp(inputValue, _minValue, _maxValue);            }            else            {                // 转换失败:重置为当前有效值                _currentValue = Math.Clamp(_currentValue, _minValue, _maxValue);            }            // 格式化后显示            FormatTextByCurrentConfig();        }        /// <summary>        /// 根据当前配置格式化文本显示        /// </summary>        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;        }        /// <summary>        /// 校验当前值是否在合法范围内        /// </summary>        private void ValidateCurrentValue()        {            _currentValue = Math.Clamp(_currentValue, _minValue, _maxValue);        }        #endregion        #region 公共方法:手动刷新数值(外部调用)        /// <summary>        /// 手动刷新数值校验与格式化        /// </summary>        public void RefreshNumericValue()        {            ValidateAndFormatInput();        }        #endregion    }}

三、控件使用方法

步骤 1:添加控件到窗体

  1. 将上述代码放入 WinForms 项目(或编译为类库)
  2. 在 Visual Studio 工具箱中,右键→「选择项」→「浏览」→ 选中编译后的程序集,NumericInputBox会出现在工具箱中
  3. 拖拽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();        }        // 示例1:配置整数输入框(0-100,不允许负数)        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// 初始值设为50        }        // 示例2:配置浮点数输入框(-100.00-200.00,保留2位小数)        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; // 初始值设为36.89        }        // 示例3:获取当前输入的数值        private void btnGetValue_Click(object sender, EventArgs e)        {            decimal currentNum = numericInputBox1.CurrentValue;            MessageBox.Show($"当前数值:{currentNum}""数值获取", MessageBoxButtons.OK, MessageBoxIcon.Information);        }        // 示例4:手动设置数值并刷新        private void btnSetValue_Click(object sender, EventArgs e)        {            numericInputBox1.CurrentValue = 88.88m;            numericInputBox1.RefreshNumericValue(); // 手动刷新格式化        }    }}

四、关键特性说明

  1. 核心继承
    :直接继承TextBox,完全复用默认输入框的所有交互逻辑(光标操作、复制粘贴、快捷键等),无需额外封装基础功能
  2. 精准输入控制
    • 类型过滤:仅允许整数 / 浮点数输入,自动屏蔽字母、特殊符号等非法字符
    • 范围约束:通过MinValue/MaxValue限制数值范围,超出范围自动截断到合法值
    • 负数控制:通过AllowNegative开关控制是否允许输入负号,灵活适配不同场景
  3. 人性化格式化
    • 数值右对齐:更符合数值输入的使用习惯
    • 小数位数控制:浮点数类型下可设置 0-8 位小数,自动补零格式化
    • 失去焦点自动校准:输入完成后自动校验合法性并格式化,避免无效数值
  4. 设计时支持
    :属性分类显示,可视化配置无需编写代码,降低使用门槛
  5. 高兼容性
    :支持直接绑定数据(如BindingSource),可集成到现有 WinForms 项目中,替换默认TextBox无成本


阅读原文:原文链接


该文章在 2026/1/19 10:36:00 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved