我的表单上有很多NumericUpDown
字段,每当用户编辑其中一个时,我希望所有这些字段都重新计算。
不用说我不能只使用ValueChanged
事件,因为它也是由程序更改触发的,这给了我们一个无限循环。
那么如何区分用户进行的调整和程序化的属性更改呢?
我需要用户能够以两种方式编辑字段 - 通过单击递增/递减按钮和直接编辑字段文本。
我的表单上有很多NumericUpDown
字段,每当用户编辑其中一个时,我希望所有这些字段都重新计算。
不用说我不能只使用ValueChanged
事件,因为它也是由程序更改触发的,这给了我们一个无限循环。
那么如何区分用户进行的调整和程序化的属性更改呢?
我需要用户能够以两种方式编辑字段 - 通过单击递增/递减按钮和直接编辑字段文本。
如果你不想要一个全局标志,你总是可以在以编程方式更改值之前暂时取消事件:
private void MyMethod()
{
numericUpDown.ValueChanged -= numericUpDown_ValueChanged;
numericUpDown.Value = 100;
numericUpDown.ValueChanged += numericUpDown_ValueChanged;
}
您可以使用一些Reflection
有关内部字段的通知,currentValue
并像这样创建自己的NumericUpDown
:
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)
您可以在以编程方式更改值时设置一个标志,然后再将其设置回来,然后您可以检查值已更改事件中的标志,并在以编程方式设置值时忽略该事件。
没有直接的方法来判断给定的变化是由用户还是由代码引起的。在这些情况下,我通常做的是依赖全局标志。示例代码:
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;
}
这是我在 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
使用仅在用户从界面更改值时触发的Validated事件处理程序。此事件在ValueChanged之后触发,并且不会在您以编程方式更改值时触发。