Reputation: 287
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).
Upvotes: 0
Views: 4560
Reputation: 1249
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!
Upvotes: 4