【问题标题】:Determine list of event handlers bound to event确定绑定到事件的事件处理程序列表
【发布时间】:2009-06-26 10:15:34
【问题描述】:

我有一个不会关闭的 WinForms 表单。在 OnFormClosing 中,e.Cancel 设置为 true。我猜我的应用程序中的某些对象已绑定到 Closing 或 FormClosing 事件,并且正在阻止关闭。为了找出答案,我想确定哪些代表绑定到这些事件之一。

有没有办法确定绑定到事件的处理程序列表?理想情况下,我会通过 Visual Studio 调试器执行此操作,但可以在应用程序中编写代码以在必要时查找处理程序。了解事件就像一个隐藏的私有字段,我已经通过调试器导航到我的表单的“Windows.Forms.Form”祖先的“非公共字段”,但无济于事。

【问题讨论】:

    标签: c# visual-studio-2008 debugging events


    【解决方案1】:

    简而言之,您不应该这样做 - 而是出于调试目的......

    事件通常由私有字段支持 - 但不包含控件;他们使用EventHandlerList 方法。您必须访问表单的受保护Events 成员,查找映射到(私有)EVENT_FORMCLOSING 对象的对象。

    一旦你有了FormClosingEventHandlerGetInvocationList 应该可以完成这项工作。


    using System;
    using System.ComponentModel;
    using System.Reflection;
    using System.Windows.Forms;
    class MyForm : Form
    {
        public MyForm()
        { // assume we don't know this...
            Name = "My Form";
            FormClosing += Foo;
            FormClosing += Bar;
        }
    
        void Foo(object sender, FormClosingEventArgs e) { }
        void Bar(object sender, FormClosingEventArgs e) { }
    
        static void Main()
        {
            Form form = new MyForm();
            EventHandlerList events = (EventHandlerList)typeof(Component)
                .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
                .GetValue(form, null);
            object key = typeof(Form)
                .GetField("EVENT_FORMCLOSING", BindingFlags.NonPublic | BindingFlags.Static)
                .GetValue(null);
    
            Delegate handlers = events[key];
            foreach (Delegate handler in handlers.GetInvocationList())
            {
                MethodInfo method = handler.Method;
                string name = handler.Target == null ? "" : handler.Target.ToString();
                if (handler.Target is Control) name = ((Control)handler.Target).Name;
                Console.WriteLine(name + "; " + method.DeclaringType.Name + "." + method.Name);
            }
        }
    }
    

    【讨论】:

    • 我也有同样的需求;在Control 中,识别键以EventMouseDown 之类的方式命名,而不是EVENT_MOUSEDOWN,因为它们用于Form
    • 对于尝试使用一堆 Windows 控件但不知道为什么 CheckBox.CheckedChangedCheckBox.CheckStateChanged 不起作用的任何人,请参阅 stackoverflow.com/a/27413251/492
    【解决方案2】:

    问题可能是表单无法验证。

    FormClosing 事件由Form 中的私有WmClose 方法引发,该方法将e.Cancel 初始化为!Validate(true)。我没有调查,但在某些情况下,Validate 将始终返回false,导致无论任何事件处理程序都取消关闭。

    要对此进行调查,请启用.Net source debugging,在FormClosing 处理程序中放置一个断点,转到Form.WmClose 的源(在调用堆栈上),在WmClose 的开头放置一个断点,然后关闭再次表格。然后,在调试器中单步执行它,看看为什么Validate 返回false。 (或者哪个事件处理程序将e.Cancel 设置为true)

    要解决此问题,请在您自己的处理程序中将e.Cancel 设置为false

    【讨论】:

      猜你喜欢
      • 2016-05-26
      • 2012-11-01
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2017-10-05
      相关资源
      最近更新 更多