Reputation: 64207
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.
Upvotes: 2
Views: 6853
Reputation: 547
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.
Upvotes: 0
Reputation: 55
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
Upvotes: 1
Reputation: 63317
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)
Upvotes: 3
Reputation: 26048
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;
}
Upvotes: 6
Reputation: 419
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.
Upvotes: 2
Reputation:
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;
}
Upvotes: 1