【问题标题】:How can I determine if an event was fired by a user action or by code?如何确定事件是由用户操作还是由代码触发的?
【发布时间】:2010-06-23 17:18:17
【问题描述】:

我在一个表单上有一堆控件,它们的所有“更改”事件都指向同一个事件处理程序。其中一些是 txtInput1 的 TextChanged、chkOption1 的 CheckedChanged 和 cmbStuff1 的 SelectedIndexChanged。这是事件处理程序:

private void UpdatePreview(object sender, EventArgs e)
{
    // TODO: Only proceed if event was fired due to a user's clicking/typing, not a programmatical set
    if (sender.IsSomethingThatTheUserDid) // .IsSomethingThatTheUserDid doesn't work
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}

我希望 if 语句仅在用户更改 TextBox 文本或单击复选框或其他任何内容时运行。如果程序的其他部分更改了文本或复选框,我不希望发生这种情况。

【问题讨论】:

  • 我可以发誓我最近刚刚回答了一个完全一样的问题......
  • 在这里。它不完全是一个完整的副本,但答案仍然是一样的:stackoverflow.com/questions/3071811/…
  • 您能否澄清一下您说“如果程序的其他部分更改了文本或复选框,我不希望发生这种情况。”
  • 我想补充的一点是,如果您想阻止事件代码运行,这将起作用。但是,如果您的事件被调用很多次甚至可能数百次,这不会使您免于性能问题。您将需要研究取消挂钩和抑制事件。

标签: c# .net events


【解决方案1】:

没有内置机制来执行此操作。但是,您可以使用标志。

bool updatingUI = false;

private void UpdatePreview(object sender, EventArgs e)
{
    if (updatingUI) return;

    txtPreview.Text = "The user has changed one of the options!";
}

然后,当您从代码更新 UI 时:

updatingUI = true;

checkBox1.Checked = true;

updatingUI = false;

如果你想过度设计解决方案,你可以使用这样的东西:

private void UpdateUI(Action action)
{
    updatingUI = true;

    action();

    updatingUI = false;
}

并像这样使用它:

UpdateUI(()=>
{
    checkBox1.Checked = true;
});

【讨论】:

  • 谢谢,我只是假设有一个内置机制可以做到这一点。我会用一面旗帜。另外,我在您上一个代码块中的语法中学到了一些新东西:)
  • @Coder:它被称为 lambda 表达式。你应该找到很多关于它们的信息。祝你好运!
【解决方案2】:

你不能只检查发件人吗?如果它从有线事件调用到 UI 控件,它将与控件一起返回。如果您从代码中触发事件,它可以是进行调用的组件,或者您可以随意设置:

private void SomewhereElse()
{
   UpdatePreview(null, new EventArgs());
}

private void UpdatePreview(object sender, EventArgs e)
{
    if (sender == null) 
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}

或者你可以这样做:

private void UpdatePreview(object sender, EventArgs e)
{
    if (!(sender is Control)) 
    {
        txtPreview.Text = "The user has changed one of the options!";
    }
}

【讨论】:

  • 这是不正确的。发送者始终是引发事件的对象。无论Text 属性是通过输入还是通过代码更改的,sender 变量将始终是引发事件的文本框的实例。
  • 从其他地方调用的不是“UpdatePreview()”,而是文本或复选框的设置(txtInput1.Text =“来自其他地方的Hello”)
  • @Adam - 从回答发布的问题的角度来看,这是不正确的。我误读了他想做什么。在我发布的上下文中,我的回答是正确的。 @Coder7862396 - 你完全正确。我在原始帖子中错过了这一点。
  • 我理解你的意思,但你说的是“从代码中触发事件”。调用事件处理程序与触发事件不同;触发事件的唯一方法是对控件执行某些操作以使其触发事件,这意味着答案不正确(sender 将始终在触发/调用事件时引用发送控件,无论来源)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
相关资源
最近更新 更多