简体   繁体   中英

Update Value of the NumericUpDown control without raising of ValueChanged event (Winforms)

I need to update a Value of the NumericUpDown control without raising of ValueChanged event (WinForms, C#).
The simple way is to remove event handler like:

numericUpDown.ValueChanged -= numericUpDown_ValueChanged;

After that to set the needed value:

numericUpDown.Value = 15;

And to add the event handler again:

numericUpDown.ValueChanged += numericUpDown_ValueChanged;

The problem is that I want to write method that will get the NumericUpDown control as a first parameter, needed value as a second parameter and will update the value in the way that was given below.
To do it, I need to find the connected event handler for the ValueChanged event (for each NumericUpDown it's different).
I searched a lot, but didn't find the solution that would work for me.
My last try was:

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);
}

After running of NumericUpDownSetValueWithoutValueChangedEvent function, the object current is equal to null, so no one EventHandler was not found (I tried it on the Form - all event handlers were found).

Have you tried changing just the internal value and updating the text instead? That way you can bypass the eventhandler being fired.

If you take a look at the source code ( http://referencesource.microsoft.com/System.Windows.Forms/winforms/Managed/System/WinForms/NumericUpDown.cs.html#0aaedcc47a6cf725 ) You will see that the property Value is using a private field called currentValue this is the value you would like to set. And afterwards just do control.Text = value.ToString();

Example

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();
    }
}

This hasnt been tested but I'm pretty sure it will work. :) Happy coding!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM