如何自定义NumericUpDown,让ValueChanged事件传递CancelEventArgs?
实现可取消值变更的自定义NumericUpDown控件
你遇到的问题核心在于:基类NumericUpDown的OnValueChanged方法签名是固定的(接收EventArgs),重写方法必须完全匹配基类的参数类型,所以你的代码才会报错。而且原ValueChanged事件是在值已经改变后触发的,就算能修改参数,也没法实现“取消编辑”的需求。不过别担心,我们可以换个思路:新增一个带CancelEventArgs的自定义事件,同时拦截所有可能修改值的操作,在值真正改变前触发这个事件,让你有机会取消编辑。
1. 自定义控件完整代码
创建一个继承自NumericUpDown的类,重写必要的方法并添加自定义事件:
using System.Windows.Forms; public class CancelableNumericUpDown : NumericUpDown { // 定义带取消功能的自定义事件 public event CancelEventHandler CancelableValueChanged; // 重写Value属性,拦截直接设置值的操作 public override decimal Value { get => base.Value; set { decimal originalValue = base.Value; // 值未变化时直接返回,避免不必要的事件触发 if (originalValue == value) return; CancelEventArgs e = new CancelEventArgs(); // 触发自定义取消事件 OnCancelableValueChanged(e); if (!e.Cancel) { // 允许变更,调用基类设置值 base.Value = value; } else { // 取消变更,恢复文本框显示原数值 Text = originalValue.ToString(FormatString); } } } // 重写UpButton方法,拦截向上按钮操作 public override void UpButton() { decimal newValue = base.Value + base.Increment; CancelEventArgs e = new CancelEventArgs(); OnCancelableValueChanged(e); if (!e.Cancel) { base.UpButton(); } } // 重写DownButton方法,拦截向下按钮操作 public override void DownButton() { decimal newValue = base.Value - base.Increment; CancelEventArgs e = new CancelEventArgs(); OnCancelableValueChanged(e); if (!e.Cancel) { base.DownButton(); } } // 触发自定义事件的保护方法 protected virtual void OnCancelableValueChanged(CancelEventArgs e) { CancelableValueChanged?.Invoke(this, e); } }
2. 使用示例(实现两个控件值不同的需求)
在窗体中添加两个CancelableNumericUpDown控件(假设命名为num1和num2),然后绑定自定义事件:
private void num1_CancelableValueChanged(object sender, CancelEventArgs e) { var currentCtrl = sender as CancelableNumericUpDown; if (currentCtrl != null && currentCtrl.Value == num2.Value) { e.Cancel = true; MessageBox.Show("两个数值不能相同,请重新输入!"); } } private void num2_CancelableValueChanged(object sender, CancelEventArgs e) { var currentCtrl = sender as CancelableNumericUpDown; if (currentCtrl != null && currentCtrl.Value == num1.Value) { e.Cancel = true; MessageBox.Show("两个数值不能相同,请重新输入!"); } }
这样不管是直接修改控件值,还是点击上下按钮,都会先触发自定义的取消事件,你可以在事件处理逻辑中判断是否允许值变更。
内容的提问来源于stack exchange,提问作者PrinceOfBorgo




