8
votes

In C#, the Changed event for a control (say, a numericupdown) gets fired whether the value was change directly by the user or if it was changed programatically as the result of some other event.

Is there a way to determine whether the event occurred as a result of user input? For example, both manually changing the value of numericUpDown1 and clicking on button1 will display "value changed". What if I only wanted to display "value changed" if it was changed through the user clicking on the up/down arrows in the control and not as a result of clicking on button1?

    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        MessageBox.Show("value changed");
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        numericUpDown1.Value = 3;
    }
6

6 Answers

5
votes

There is no nice way to do it. You can find workarounds for specific cases, e.g.

  • listen to MouseDown or something instead of valueChanged on the numeric drop down.

  • Set a flag in button click event handler that will prohibit the message box from showing.

    In general you should try to organize your form in a way that it doesn't matter where the value got changed.

5
votes

You could check to see if the numericUpDown is the ActiveControl. When you set the value of the numericUpDown during the button click, button1 should be the ActiveControl. When the user changes the value via the numericUpDown, then the numericUpDown should be the ActiveControl.

if(numericUpDown1 == this.ActiveControl)
{
    MessageBox.Show("value changed");
}
1
votes

No, there is no built-in way to do what you are trying to do as the code to trigger the event is firing when the value changes.

0
votes
  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 solution in VB .NET

    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
0
votes

One interesting case is the ComboBox control, which does differentiate between changes in the selection by the SelectionChangeCommitted event, which is raised only when the user makes a change via the GUI, and the SelectedIndexChanged event, which is raised every time the SelectedIndex property changes. You could examine the source for the ComboBox and see how it's done. Of course, there's no guarantee that the principle will be transferable to other controls.

0
votes

I have solved this problem before. Let's take the NumericUpDown control as an illustrative example.

First, create a new control (call it MyNumericUpDown) that inherits from the NumericUpDown. Create overrides for the UpButton, DownButton, and OnLostFocus methods. Also create a public method for setting the value of the control programmatically. Create an enum type called 'ValueChangedType' that has 4 different values called TextEdit, UpButton, DownButton, and Programmatic (or call them whatever you like). Also create a property called ChangedType of type ValueChangedType. Here is what the class looks like.

public partial class MyNumericUpDown : NumericUpDown
{
    public enum ValueChangedType
    {
        TextEdit,
        UpButton,
        DownButton,
        Programmatic
    }
    public ValueChangedType ChangedType = ValueChangedType.Programmatic;
    public MyNumericUpDown()
    {
        InitializeComponent();
    }
    public override void UpButton()
    {
        this.ChangedType = ValueChangedType.UpButton;
        base.UpButton();
    }
    public override void DownButton()
    {
        this.ChangedType = ValueChangedType.DownButton;
        base.DownButton();
    }
    protected override void OnLostFocus(EventArgs e)
    {
        this.ChangedType = ValueChangedType.TextEdit;
        base.OnLostFocus(e);
    }
    public void SetValue(decimal val)
    {
        this.ChangedType = ValueChangedType.Programmatic;
        this.Value = val;
    }
}

Now, in your form, create a MyNumericUpDown control (call it 'myNUD'). In the ValueChanged event handler for the control, you can get the value of the ChangedType property, and do something with it:

    private void myNUD_ValueChanged(object sender, EventArgs e)
    {
            MyNumericUpDown nud = sender as MyNumericUpDown;
            var myChangedType = nud.ChangedType;
            /* do something */
    }