Question

Having many NumericUpDown fields on my form I want all of them recalculated whenever a user edits one of them.

Needless to say I can't just use ValueChanged event because it is also triggered by programmatic change which gives us an infinite loop.

So how can I distinguish user-made adjustments from programmatic property changes?

I need a user to be able of editing the fields both ways - by clicking increment/decrement buttons and by editing the field text directly.

Was it helpful?

Solution

If you don't want a global flag you can always temporarily unwire the event right before changing the value programatically:

private void MyMethod()
{
    numericUpDown.ValueChanged -= numericUpDown_ValueChanged;
    numericUpDown.Value = 100;
    numericUpDown.ValueChanged += numericUpDown_ValueChanged;
}

OTHER TIPS

You can use some Reflection with a notice about the internal field currentValue and create your own NumericUpDown like this:

public class CustomNumericUpDown : NumericUpDown {
    static System.Reflection.FieldInfo currentValue;
    static CustomNumericUpDown() {
        currentValue = typeof(NumericUpDown).GetField("currentValue",
                             System.Reflection.BindingFlags.NonPublic | 
                             System.Reflection.BindingFlags.Instance);
    }
    public CustomNumericUpDown() {
        RaiseValueChangedOnlyByUser = true;
    }
    public bool RaiseValueChangedOnlyByUser { get; set; }
    public new decimal Value {
        get { return base.Value; }
        set
        {
            if (RaiseValueChangedOnlyByUser){
                currentValue.SetValue(this, value);
                UpdateEditText();
            }
            else base.Value = value;
        }
    }
}
//Then in your code just use the `Value` normally, it won't
//never fire the ValueChanged event unless user changes it via the UI
//You can set the RaiseValueChangedOnlyByUser to false to 
//enable firing ValueChanged when the value is changed by code (like as 
//the standard NumericUpDown does)

You could, when changing the value programmatically set a flag & then set it back afterwards, then you can check the flag in Value Changed event and ignore the event when you are setting the values programmatically.

There is no direct way to tell if the given variation was provoked by the user or by the code. What I usually do in these situations is relying on a global flag. Sample code:

bool autoChanged;
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
    if (!autoChanged)
    {
        //Perform actions you wish when the value is changed by the user
    }
    autoChanged = false;
}

private void button1_Click(object sender, EventArgs e)
{
    autoChanged = true; //Setting the flag to true every time the .Value property is modified via code
    numericUpDown1.Value = 5;
}
  1. Inherit NumericUpDown Class
  2. Create a flag for determine value changed programmatically, or changed by GUI
  3. Overload Value Property to set above flag

Here is my implementation in VB .NET. Also work in case of data binding

Private m_blnIsValueChangedByGui As Boolean = True

Public Property IsValueChangedByGui() As Boolean
    Get
        Return m_blnIsValueChangedByGui
    End Get
    Set(ByVal value As Boolean)
        m_blnIsValueChangedByGui = value
    End Set
End Property

Public Shadows Property Value() As Decimal
    Get
        Return MyBase.Value
    End Get
    Set(ByVal value As Decimal)
        IsValueChangedByGui = False

        If (value > Me.Maximum) Then
            MyBase.Value = Me.Maximum
        ElseIf (value < Me.Minimum) Then
            MyBase.Value = Me.Minimum
        Else
            MyBase.Value = value
        End If

        IsValueChangedByGui = True
    End Set
End Property

Use the Validated event handler that triggers only when the user changes the value from the interface. This event triggers after the ValueChanged and will not be triggered when you change the value programmatically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top