- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
NumericUpDown 是 HandyControl 提供的数值选择控件,它把"一对可点击调整数值的箭头按钮"与一个 TextBox 组合在一起,用来显示并设置数值(Value)。用户既可以通过点击向上/向下箭头按钮逐级调整,也可以直接在控件的 TextBox 部分键入数字来改变Value。本篇指南以 NumericUpDown 数值选择控件文档 为主体,结合 NumericUpDown.cs 源码 与 NumericUpDown.xaml 样式,带你从基础创建、数值格式化、步进与边界控制,一路深入到带标题/占位符/清除按钮的进阶形态,读完即可在 WPF 项目中直接落地使用。
NumericUpDown 是什么:结构与模板约定
从源码看,NumericUpDown 继承自Control,并且通过TemplatePart声明了它内部必须包含一个名为PART_TextBox的TextBox:
[TemplatePart(Name = ElementTextBox, Type = typeof(TextBox))] public class NumericUpDown : Control这个约定意味着:NumericUpDown 的数值输入核心就是它模板里的一个 TextBox。在 NumericUpDown.cs 中,ElementTextBox常量为"PART_TextBox";当模板应用(OnApplyTemplate)时,控件会通过GetTemplateChild(ElementTextBox)取到该 TextBox,并把SelectionBrush、CaretBrush等外观属性同步绑定过去,同时挂接PreviewKeyDown、TextChanged、LostFocus三个关键事件来完成键盘输入解析与失焦校验。
默认外观模板定义在 NumericUpDownBaseStyle.xaml:
- 主体是一个
hc:WatermarkTextBox(水印文本框,用于承载占位符文本); - 右侧纵向排列两个
RepeatButton,即 UpButton 与 DownButton,分别绑定interactivity:ControlCommands.Prev与ControlCommands.Next命令(这两个命令在 ControlCommands.cs 中统一定义); - 当
IsEnabled=false时整个 root 透明度降为 0.4;鼠标悬停时边框变为SecondaryBorderBrush,获得焦点时边框变为PrimaryBrush。
创建 NumericUpDown 并设置 Value
创建控件并在 XAML 中设置初始值:
<hc:NumericUpDown Value="100"/>在代码后置(Code-behind)中创建并赋值:
var numericUpDown = new NumericUpDown(); numericUpDown.Value = 100;Value 的底层行为
Value是类型为double的依赖属性,在 NumericUpDown.cs 中注册:
- 默认双向绑定:注册时使用了
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,因此<hc:NumericUpDown Value="{Binding ...}"/>无需额外指定Mode即可实现 VM 与控件的双向同步; - 带强制回调(CoerceValue):
Value受Minimum/Maximum约束,越界值会被强制拉回边界(详见下文"上限和下限"一节); - 默认值 0:使用
ValueBoxes.Double0Box作为默认元数据。
当Value改变时,控件会调用SetText()刷新内部 TextBox 的显示文本,并触发冒泡路由事件ValueChanged。
设置 DecimalPlaces 控制小数位数
如果希望约束Value显示的小数位数,可以设置DecimalPlaces。它是一个int?(可空 int)属性:当值为null时不限制小数位显示,否则按指定位数显示。
<hc:NumericUpDown DecimalPlaces="2" Value="100.12345"/>numericUpDown.Value = 10.12345; numericUpDown.DecimalPlaces = 2;在 NumericUpDown.cs 中,DecimalPlaces注册为typeof(int?),默认值default(int?)即null。显示文本由CurrentText属性生成:
private string CurrentText => string.IsNullOrWhiteSpace(ValueFormat) ? DecimalPlaces.HasValue ? Value.ToString($"#0.{new string('0', DecimalPlaces.Value)}") : Value.ToString() : Value.ToString(ValueFormat);即当DecimalPlaces为 2 时,格式化串为#0.00,100.12345会显示为100.12。需要强调的是:DecimalPlaces只影响显示格式,不改变Value本身,Value依然保留完整精度。
进阶:ValueFormat 覆盖格式化
除了DecimalPlaces,控件还提供了ValueFormat字符串属性(NumericUpDown.cs),它直接作为 .NET 数字格式串传给Value.ToString(format),并且会覆盖DecimalPlaces的设置。例如在 NumericUpDownDemo.xaml 的官方示例中:
<hc:NumericUpDown ValueFormat="N2" Maximum="100000" Value="10000" Width="380"/>N2会以千位分隔符 + 两位小数的方式显示数值(如 10,000.00),适合金额等场景。
设置 Increment 调整步进量
Increment决定每单击一次向上/向下按钮时数值增加或减少的幅度。
<hc:NumericUpDown Value="100" Increment="10"/>numericUpDown.Increment = 10;Increment的默认值是 1(NumericUpDown.cs 中使用ValueBoxes.Double1Box)。它影响所有调整数值的入口,而不仅仅是按钮点击:
- 点击UpButton:执行
ControlCommands.Prev,即Value + Increment; - 点击DownButton:执行
ControlCommands.Next,即Value - Increment; - 在 TextBox 聚焦时按↑ / ↓ 方向键(
TextBox_PreviewKeyDown):分别执行Value ± Increment; - 在 TextBox 聚焦时滚动鼠标滚轮(
OnMouseWheel):Value += e.Delta > 0 ? Increment : -Increment。
可见Increment是全部调值路径的统一步长。需要指出的是,源码中命令绑定使用的ControlCommands.Prev/Next与常规直觉相反——Prev对应"数值增加"(向上按钮),Next对应"数值减少"(向下按钮),这与控件内部 NumericUpDown.cs 的命令实现一致。
设置 Maximum 和 Minimum 约束上下限
通过Maximum与Minimum可以限制Value的合法范围:
<hc:NumericUpDown Maximum="500" Minimum="10"/>numericUpDown.Minimum = 10; numericUpDown.Maximum = 1000;两个属性的默认值分别是double.MaxValue与double.MinValue(NumericUpDown.cs),即默认不设边界。它们的约束是双向联动的:
CoerceValue强制回调:当Value < Minimum时被拉回Minimum,当Value > Maximum时被拉回Maximum;CoerceMaximum:Maximum不允许小于当前Minimum,否则取Minimum值;CoerceMinimum:Minimum不允许大于当前Maximum,否则取Maximum值;- 修改
Minimum会重新强制Maximum与Value,修改Maximum会重新强制Minimum与Value(OnMinimumChanged、OnMaximumChanged)。
同时,TextBox 在输入过程中(TextBox_TextChanged)也只有在value >= Minimum && value <= Maximum时才会把输入值写回Value,保证边界约束贯穿"键盘输入"与"按钮步进"两条路径。在官方示例 NumericUpDownDemo.xaml 中可以看到Maximum="100"的典型用法。
设置标题(Title)与占位符(Placeholder)
你可以为 NumericUpDown 添加Header(标题)和Placeholder(占位符),向用户提示其用途。使用这两个附加属性需要先应用NumericUpDownExtend样式(原文档写作NumericUpDownPlus,注意区分:NumericUpDownExtend负责标题与占位符,NumericUpDownPlus在此基础上额外增加清除按钮):
<hc:NumericUpDown hc:InfoElement.Placeholder="{x:Static langs:Lang.PlsEnterContent}" hc:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr1}" Style="{StaticResource NumericUpDownExtend}" />这两个附加属性定义在 InfoElement.cs 中:
InfoElement.Placeholder:占位符文本,注册为Inherits(可继承)的附加属性,默认null;InfoElement.Title:标题文本,继承自TitleElement基类;- 此外还有
InfoElement.Necessary(是否必填)、InfoElement.Symbol(必填标记符号,默认●)、InfoElement.ContentHeight/MinContentHeight(内容高度,默认 28.0)等配套附加属性。
对应地,NumericUpDownExtend样式的模板(见 NumericUpDownBaseStyle.xaml)分为两种:
- 标题在顶部(默认,
NumericUpDownExtendTopTemplate); - 标题在左侧(当
InfoElement.TitlePlacement="Left"时切换为NumericUpDownExtendLeftTemplate),此时可用InfoElement.TitleWidth控制标题列宽。
NumericUpDownExtend样式本身在 NumericUpDown.xaml 中定义,直接BasedOn="{StaticResource NumericUpDownExtendBaseStyle}"。
标题在左侧的进阶用法
参照官方示例 NumericUpDownDemo.xaml:
<hc:NumericUpDown Width="380" hc:InfoElement.TitleWidth="140" hc:InfoElement.TitlePlacement="Left" hc:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr3}" Style="{StaticResource NumericUpDownExtend}"/>清除按钮与校验:NumericUpDownPlus 样式
在NumericUpDownExtend的基础上,NumericUpDownPlus样式(NumericUpDown.xaml)额外加入了一个清除按钮(ButtonClear,使用DeleteFillCircleGeometry图标),默认Collapsed隐藏,只有当鼠标悬停、InfoElement.ShowClearButton="True"且非只读时(模板中的MultiTrigger条件,见 NumericUpDownBaseStyle.xaml)才显示。点击清除按钮会执行ControlCommands.Clear,把Value重置为 0(ValueBoxes.Double0Box)。
InfoElement.ShowClearButton附加属性定义于 InfoElement.cs,默认false。
配合数据绑定与校验规则,可以实现带清除功能的表单控件。官方示例 NumericUpDownDemo.xaml 展示了完整写法:
<hc:NumericUpDown hc:InfoElement.ShowClearButton="True" Style="{StaticResource NumericUpDownPlus}"> <hc:NumericUpDown.Value> <Binding Path="DoubleValue1" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <tools:NumericUpDownDemoRule/> </Binding.ValidationRules> </Binding> </hc:NumericUpDown.Value> </hc:NumericUpDown>对应的校验规则 NumericUpDownDemoRule.cs 演示了如何校验输入必须为偶数:当值不是double时返回FormatError错误,当值不能被 2 整除时返回Error错误,否则返回ValidationResult.ValidResult。
其他实用属性:只读、禁用与小型样式
在官方示例 NumericUpDownDemo.xaml 中还展示了两种常用状态:
<hc:NumericUpDown Maximum="100"/> <hc:NumericUpDown IsEnabled="False"/> <hc:NumericUpDown IsReadOnly="True"/>IsReadOnly:只读属性(NumericUpDown.cs,默认false)。为true时禁用箭头按钮(模板中Boolean2BooleanReConverter反转绑定)、键盘方向键、滚轮与清除命令均不会生效;用户仍可聚焦但无法修改数值。对应模板在 NumericUpDownBaseStyle.xaml 中IsReadOnly=True时禁用 UpButton/DownButton;IsEnabled="False":整控件禁用,模板自动将透明度降为 0.4。
HandyControl 还内置了紧凑尺寸样式NumericUpDown.Small、NumericUpDownExtend.Small、NumericUpDownPlus.Small(NumericUpDown.xaml),它们把内容高度与最小高度设为 20,适合工具栏等紧凑布局。此外ShowUpDownButton(NumericUpDown.cs,默认true)允许隐藏上下调值按钮,仅保留文本框输入。
属性与事件速查表
下表汇总了 NumericUpDown 的全部核心属性(对应文档"属性"小节):
| 属性 | 描述 | 默认值(源码依据) |
|---|---|---|
| Value | 获取或设置当前值 | 0(双向绑定,受 Maximum/Minimum 强制约束) |
| Maximum | 获取或设置最大允许值 | double.MaxValue |
| Minimum | 获取或设置最小允许值 | double.MinValue |
| Increment | 获取或设置单击向上或向下按钮时,数字显示框(也称作 up-down 控件)递增或递减的值 | 1 |
| DecimalPlaces | 获取或设置 NumericUpDown 中要显示的十进制位数。此属性不会影响 Value 属性 | null(不限制小数位) |
| ValueFormat | 数字格式串,覆盖 DecimalPlaces | null |
| IsError | 获取或设置数据是否错误 | — |
| ErrorStr | 获取或设置错误提示 | — |
| TextType | 获取或设置文本类型 | — |
| ShowClearButton | 获取或设置是否显示清除按钮(InfoElement.ShowClearButton附加属性) | false |
| IsReadOnly | 是否只读 | false |
| ShowUpDownButton | 是否显示上下调值按钮 | true |
注:
IsError、ErrorStr、TextType三项在文档属性表中列出,属于与输入校验联动、由外部绑定(如验证规则失败)驱动的状态属性,实际效果可在 demo 中配合ValidationRule观察。
事件:
| 事件 | 描述 |
|---|---|
| ValueChanged | 在以某种方式更改 Value 属性后发生(冒泡路由事件,事件参数类型EventHandler<FunctionEventArgs<double>>,携带新值Info) |
ValueChanged的注册细节见 NumericUpDown.cs,使用方式示例:
numericUpDown.ValueChanged += (s, e) => { var newValue = e.Info; // 新值 };常见问题与注意事项
- DecimalPlaces 不改变 Value 精度:显示四舍五入到指定位数,但
Value仍是完整 double,适合"显示约束 + 完整精度"的货币/科学计算场景。 - ValueFormat 优先于 DecimalPlaces:两者同时设置时以
ValueFormat为准(见CurrentText的三分支判断)。 - 边界自动收敛:
Value、Minimum、Maximum三者存在一致性约束,任意一个变化都可能连带修正另外两者,绑定数据时无需手工防越界。 - 失焦兜底:TextBox 失焦时若文本为空,
Value会被重置为 0;若文本非法(无法解析为 double),则恢复为当前值的显示文本(SetText(true)),避免留下脏数据。 - 不同样式适用不同场景:
NumericUpDownBaseStyle(默认)适合简单输入;NumericUpDownExtend增加标题/占位符/必填标记;NumericUpDownPlus再增加清除按钮。对应关系为NumericUpDownPlusBaseStyle → NumericUpDownExtendBaseStyle → NumericUpDownBaseStyle,后者逐级继承。
若需查看完整可运行的示例,可直接参考官方 Demo 的 NumericUpDownDemo.xaml(四种样式 × 三种状态共 12 个实例)及其配套的 NumericUpDownDemoRule.cs 校验规则。
- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
相关推荐
TypeSpec 值(Value)体系完全指南:对象值、数组值、标量值与 `valueof` 约束
TypeSpec 值(Value)体系完全指南:对象值、数组值、标量值与 valueof 约束 TypeSpec 语言在类型系统之外提供了一套独立的“值(Val
编程语言编译器后端PyPTO 算子设计约束体系解析:从 API 选择到循环、Tiling 与数据流的完整边界指南
PyPTO 算子设计约束体系解析:从 API 选择到循环、Tiling 与数据流的完整边界指南 导读 本文以 CANN / pypto gym 仓库中 pypt
人工智能大模型算子库模型优化AI 技能CANNAscendHandyControl DatePicker 日期选择器控件完全指南:创建、日期选择、标题占位符与数据校验
HandyControl DatePicker 日期选择器控件完全指南:创建、日期选择、标题占位符与数据校验 HandyControl 在 WPF 原生 Sys
UI组件桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考