如何判断事件是不是来自 C# 中的用户输入?

Posted

技术标签:

【中文标题】如何判断事件是不是来自 C# 中的用户输入?【英文标题】:How to tell if event comes from user input in C#?如何判断事件是否来自 C# 中的用户输入? 【发布时间】:2013-03-11 02:24:23 【问题描述】:

我有一个小表单,上面有一些复选框,CheckChanged 事件的每个复选框都有一个消息处理程序。由于某些复选框依赖于其他复选框,如果一个复选框的选中状态发生更改,它会更改任何依赖复选框的选中状态。我发现这会导致在其他复选框上引发事件,但我的问题是每个事件都有一个函数调用,只有当事件来自用户实际单击复选框时才应调用该函数调用。我想知道如何判断(可能来自发件人或EventArgsCheckChanged 事件是否是由鼠标单击引起的。

悬崖:

多个复选框接收CheckChanged 事件 需要确定是否通过鼠标单击引发了事件

【问题讨论】:

当他们使用制表符和空格键进行导航和选择时会怎样?在尝试破坏输入法之前,我会理清你的逻辑。 我可能会断开更改的事件处理程序,然后重新连接它们。 您能否告诉我们您为什么想知道他们选择使用的是鼠标吗?它可能对我们有帮助。在我能想到的几乎所有情况下,它都没有任何区别...... @Penfold 这是一个这样的细节实际上非常清楚的问题 - 因为,副作用逻辑。 感谢您的快速回复。 @Grant,相同的规则将适用于键盘按下(我希望触发事件),因此可以将问题改写为“如何判断事件是否是由用户输入引起的,而不是作为侧面-节目效果” 【参考方案1】:

您可以使用标志来指示是否忽略事件。它可能比取消订阅事件处理程序更容易。它不是很复杂,但应该可以胜任。

我整理了一个简单的例子:

   bool ignoreEvents = false;
        public Form1()
        
            InitializeComponent();
        

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        
            ignoreEvents = true;
            checkBox2.Checked = checkBox1.Checked ;
            checkBox3.Checked = checkBox1.Checked;
            ignoreEvents = false;
        

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        
            if (ignoreEvents) return;
            MessageBox.Show("Changed in 2");
        

        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        
            if (ignoreEvents) return;
            MessageBox.Show("Changed in 3");
        

【讨论】:

这成功了,而且实现起来非常简单,谢谢!编辑:虽然没有回复可以梳理出事件处理程序的参数中的信息,但我有点失望【参考方案2】:

为了提高代码稳定性,您还可以使用类 TriggerLock 而不是 ignoreEvents 标志。

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    
        using (new TriggerLock())
        
            checkBox2.Checked = checkBox1.Checked;
            checkBox3.Checked = checkBox1.Checked;
        
    

    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    
        if (TriggerLock.IsOpened)
        
            MessageBox.Show("Changed in 2");
        
    

    private void checkBox3_CheckedChanged(object sender, EventArgs e)
    
        if (TriggerLock.IsOpened)
        
            MessageBox.Show("Changed in 3");
        
    

TriggerLock 类,它像信号量一样工作:

public class TriggerLock
    : IDisposable

    private static int _nUsing = 0;
    private bool _bDisposed;

    public TriggerLock()
    
        _bDisposed = false;
        Interlocked.Increment(ref _nUsing);
    
    ~TriggerLock()
    
        Dispose(false);
    

    public static bool IsOpened 
    
        get  return _nUsing == 0; 
    

    public void Dispose()
    
        Dispose(true);
    
    private void Dispose(bool bDisposing)
    
        if (bDisposing && !_bDisposed)
        
            Interlocked.Decrement(ref _nUsing);
            _bDisposed = true;
        
    

【讨论】:

很有趣,但是您的课程如何区分由直接用户交互引发的事件(例如,用户单击复选框)和由副作用逻辑引发的事件(例如,用户单击复选框,这会导致其他复选框来改变状态)? 该类没有隐式区分用户交互和副作用。这只是 Alex 的想法的改进(例外证明)版本。 我认为静态 _nUsing 变量是一个非常糟糕的主意。如果这个类用于同一个项目的两个不相关的部分怎么办?这将导致混乱的结束。最好使用一个实例字段,让用户在一个字段中保留这个类的对象。 这种模式在单线程的短代码段中运行良好。这是 GUI 中最常见的情况。该类允许嵌套锁定并且是异常安全的。如果您必须同时在多个对话框中锁定事件,或者您的 GUI 使用多线程,您应该更改模式。我已经在 VB6 中使用了该模式;)

以上是关于如何判断事件是不是来自 C# 中的用户输入?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中如何判断JTextField的一些问题?求高手解答……谢谢

如何将来自用户的输入图像与 C# 中数据库中存储的图像进行比较 [关闭]

如何监听Stripe cardElement 的输入事件,判断卡片是不是无效并禁用按钮?

C#如何订阅用户控件事件/用户控件没有实例名称

C# - 如何检查用户的输入是不是存在于组合框中(使用的数据绑定项)

c语言 检查输入是不是合法