【问题标题】:Determine If Changed Event Occurred from User Input Or Not确定用户输入是否发生更改事件
【发布时间】:2009-03-16 15:00:07
【问题描述】:

在 C# 中,无论值是由用户直接更改还是由于某些其他事件以编程方式更改,都会触发控件(例如 numericupdown)的 Changed 事件。

有没有办法确定事件是否是由于用户输入而发生的?例如,手动更改 numericUpDown1 的值和单击 button1 都会显示“值已更改”。如果我只想显示“值已更改”,如果它是通过用户单击控件中的向上/向下箭头而不是由于单击 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;
    }

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    没有很好的方法来做到这一点。您可以找到针对特定情况的解决方法,例如

    • 听 MouseDown 之类的,而不是数字下拉菜单上的 valueChanged。

    • 在按钮单击事件处理程序中设置一个标志,该标志将禁止显示消息框。

      一般而言,您应该尝试以与更改值无关的方式来组织表单。

    【讨论】:

    • +1 表示“最佳实践”的想法。我有同样的问题 - 设置一个场效应所有其他。我添加了很多提前退出,所以事件只有在底层数据不同时才会触发,并且逻辑会自行解开。
    【解决方案2】:

    您可以检查 numericUpDown 是否为 ActiveControl。当您在按钮单击期间设置 numericUpDown 的值时,button1 应该是 ActiveControl。当用户通过 numericUpDown 改变值时,numericUpDown 应该是 ActiveControl。

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

    【讨论】:

      【解决方案3】:

      不,没有内置方法可以执行您尝试执行的操作,因为触发事件的代码会在值更改时触发。

      【讨论】:

        【解决方案4】:
        1. 继承 NumericUpDown 类
        2. 创建一个标志以确定以编程方式更改或由 GUI 更改的值
        3. 重载值属性以设置上述标志

        这是我在 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
        

        【讨论】:

          【解决方案5】:

          一个有趣的例子是 ComboBox 控件,它确实区分了由 SelectionChangeCommitted 事件引起的选择更改,该事件仅在用户通过 GUI 进行更改时引发,而 SelectedIndexChanged 事件在每次 SelectedIndex 时引发属性变化。您可以检查 ComboBox 的源代码,看看它是如何完成的。当然,不能保证该原则可以转移到其他控件。

          【讨论】:

            【解决方案6】:

            我以前解决过这个问题。我们以 NumericUpDown 控件为例。

            首先,创建一个继承自 NumericUpDown 的新控件(称为 MyNumericUpDown)。为 UpButton、DownButton 和 OnLostFocus 方法创建覆盖。还要创建一个公共方法来以编程方式设置控件的值。创建一个名为“ValueChangedType”的枚举类型,它有 4 个不同的值,分别称为 TextEdit、UpButton、DownButton 和 Programmatic(或您喜欢的任何名称)。还要创建一个名为 ChangedType 的 ValueChangedType 类型的属性。这是这个类的样子。

            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;
                }
            }
            

            现在,在您的表单中创建一个 MyNumericUpDown 控件(称为“myNUD”)。在控件的 ValueChanged 事件处理程序中,您可以获取 ChangedType 属性的值,并对其进行处理:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-12-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-02-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多