WinForms:暂时禁用事件处理程序

42

如何在WinForms中暂时禁用事件处理程序?


你能分享一下你在更高层面上正在做什么吗?因为你可能不想禁用所有事件处理程序(例如表单的默认绘制和移动处理程序)。 - Joel Coehoorn
我只是不想在以编程方式更新控件时捕获其状态的更改。是的,我不想禁用“所有”事件处理程序,只是“一个事件处理程序”。 - George
5个回答

61

也许最简单的方法(不需要取消订阅或其他操作)是声明一个布尔值,并在处理程序开始时检查它:

bool dontRunHandler;

void Handler(object sender, EventArgs e) {
   if (dontRunHandler) return;

   // handler body...
}

13
如果经常使用这种方法,代码会变得杂乱无序。 - Sameera Kumarasingha
这不会成为竞态条件吗? - k1ngjulien
1
@k1ngjulien 如果所有东西都在同一个线程上运行,通常情况下是使用winforms。 - relatively_random
WinForms要求所有UI活动都在单个线程上进行,因此这种习惯用法在单线程应用程序中是安全的。只要满足以下两个条件,它在多线程应用程序中也是安全的:1.仅从UI(主)线程或使用.Invoke()调用函数。(要查看是否应调用Invoke(),可以检查.InvokeRequired。)2.不要直接从任何其他线程分配或读取变量。请注意,任何调用的调用将在主线程可以运行它之前不会运行,因此请注意死锁。 - shelleybutterfly

59

从什么角度禁用?如果你想要从处理程序的委托列表中删除一个在你的作用域中的方法,你可以这样做...

从什么角度禁用?

如果您想从处理程序的委托列表中移除一个在您的作用域中的方法,只需执行以下操作:

object.Event -= new EventHandlerType(your_Method);
这将从委托列表中删除该方法,您可以稍后使用特定语法重新附加它。
object.Event += new EventHandlerType(your_Method);

10
我认为你的意思是你的_Method 而不是 your_Method()。从 C# 2.0 开始,你也不需要 "new EventHandlerType" 这部分 - 只需使用 object.Event += yourMethod; 和 object.Event -= yourMethod; - Jon Skeet
是的,我本意就是不加括号的 ;). 虽然不知道隐式委托构造,但这很好知道。 - Adam Robinson
这个想法对我来说很有效(相比于被接受的答案),在我需要暂时禁用处理程序以响应组合框EditValueChanged事件的情况下。 - PhoenixDev
这应该是被接受的答案。 - Chandraprakash

3
禁用该组件的事件。 伪代码:
YourComponent.YourComponentEvent -= ExistingMethodForTheEvent;

启用

YourComponent.YourComponentEvent += ExistingMethodForTheEvent;

例如像 DataGridView 中的 CellFormatting 这样的事件:

//enabling
DataGridView1.CellFormatting += DataGridView1_CellFormatting;
//disabling
DataGridView1.CellFormatting -= DataGridView1_CellFormatting;

private void DgvBillings_CellFormatting(...) {
...
}

2
我是以这种方式进行的,使用控制扩展。
public static void SetDatasource(
  this ComboBox cb, 
  object dataSource, 
  EventHandler _SelectedIndexChanged_eventHandler = null, 
  EventHandler _SelectedValueChanged_eventHandler = null)
{
//disable events
  if (_SelectedIndexChanged_eventHandler != null) cb.SelectedIndexChanged -= _SelectedIndexChanged_eventHandler;
  if (_SelectedValueChanged_eventHandler != null) cb.SelectedValueChanged -= _SelectedValueChanged_eventHandler;
  if (cb.InvokeRequired)
  {
    cb.BeginInvoke(new _d_SetDatasource_ComboBox(SetDatasource), new object[] { cb, dataSource, _SelectedIndexChanged_eventHandler});
  }
  else
  {
    cb.DataSource = dataSource;
    //events enabled again
    if (_SelectedIndexChanged_eventHandler != null) cb.SelectedIndexChanged += _SelectedIndexChanged_eventHandler;
    if (_SelectedValueChanged_eventHandler != null) cb.SelectedValueChanged += _SelectedValueChanged_eventHandler;
  }
}
private delegate void _d_SetDatasource_ComboBox(ComboBox cb, object dataSource, EventHandler _SelectedIndexChanged_eventHandler = null, EventHandler _SelectedValueChanged_eventHandler = null);

0
如果您正在为一组复选框或单选按钮使用一个事件处理程序,您也可以使用类似以下的代码:
var lSender = sender as RadioButton;
if (lSender?.Checked != true)
    return;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接