【问题标题】:Update Value of the NumericUpDown control without raising of ValueChanged event (Winforms)在不引发 ValueChanged 事件的情况下更新 NumericUpDown 控件的值 (Winforms)
【发布时间】:2016-08-21 11:25:27
【问题描述】:

我需要在不引发 ValueChanged 事件(WinForms、C#)的情况下更新 NumericUpDown 控件的值。
简单的方法是删除事件处理程序,例如:

numericUpDown.ValueChanged -= numericUpDown_ValueChanged;

然后设置所需的值:

numericUpDown.Value = 15;

并再次添加事件处理程序:

numericUpDown.ValueChanged += numericUpDown_ValueChanged;

问题是我想编写方法,将 NumericUpDown 控件作为第一个参数,所需的值作为第二个参数,并按照下面给出的方式更新值。
为此,我需要为 ValueChanged 事件找到已连接的事件处理程序(对于每个 NumericUpDown 它都不同)。
我搜索了很多,但没有找到适合我的解决方案。
我最后一次尝试是:

private void NumericUpDownSetValueWithoutValueChangedEvent(NumericUpDown control, decimal value)
{
    EventHandlerList events = (EventHandlerList)typeof(Component).GetField("events", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField).GetValue(control);
    object current = events.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)[0].GetValue(events);
    List<Delegate> delegates = new List<Delegate>();
    while (current != null)
    {
         delegates.Add((Delegate)GetField(current, "handler"));
         current = GetField(current, "next");
    }
    foreach (Delegate d in delegates)
    {
         Debug.WriteLine(d.ToString());
    }
}
public static object GetField(object listItem, string fieldName)
{
    return listItem.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField).GetValue(listItem);
}

NumericUpDownSetValueWithoutValueChangedEvent 函数运行后,object current 等于 null,因此没有找到任何 EventHandler(我在 Form 上尝试过 - 找到了所有事件处理程序)。

【问题讨论】:

  • 我很确定不是。你能解释一下我错过了什么吗?

标签: c# winforms


【解决方案1】:

您是否尝试过仅更改内部值并更新文本?这样你就可以绕过被触发的事件处理程序。

如果你看一下源代码(http://referencesource.microsoft.com/System.Windows.Forms/winforms/Managed/System/WinForms/NumericUpDown.cs.html#0aaedcc47a6cf725) 您将看到属性 Value 正在使用一个名为 currentValue 的私有字段,这是您要设置的值。然后就做control.Text = value.ToString();

例子

private void SetNumericUpDownValue(NumericUpDown control, decimal value)
{
    if (control == null) throw new ArgumentNullException(nameof(control));
    var currentValueField = control.GetType().GetField("currentValue", BindingFlags.Instance | BindingFlags.NonPublic);
    if (currentValueField != null)
    {
        currentValueField.SetValue(control, value);
        control.Text = value.ToString();
    }
}

这还没有经过测试,但我很确定它会起作用。 :) 编码愉快!

【讨论】:

  • 在这种情况下,currentValueField 为空。
  • 哈哈哈我的错! :) 我需要修改代码,因为我不小心写道:“this.GetType()...”请再试一次;) 将 this.GetType() 替换为 control.GetType()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多