代码之家  ›  专栏  ›  技术社区  ›  JoshL

确定绑定到事件的事件处理程序列表

  •  27
  • JoshL  · 技术社区  · 16 年前

    我有一个WinForms窗体无法关闭。在onformClosing中,e.Cancel设置为true。我猜想应用程序中的某个对象已绑定到Closing或FormClosing事件,并且正在阻塞Close。为了查明原因,我想确定哪些代表与这些事件之一绑定。

    是否有方法确定绑定到事件的处理程序列表?理想情况下,我可以通过Visual Studio调试器执行此操作,但如果需要,可以在应用程序中编写代码以查找处理程序。了解到一个事件就像一个隐藏的私有字段,我已经通过调试器导航到窗体的“windows.forms.form”祖先的“非公共字段”,但是没有用。

    2 回复  |  直到 15 年前
        1
  •  31
  •   Marc Gravell    16 年前

    简而言之,您不是有意这样做的-而是为了调试目的…

    事件是 经常 由一个私有字段支持-但不带控件;它们使用 EventHandlerList 方法。您必须访问受保护的表单 Events 成员,正在查找映射到(private)事件_FormClosing对象的对象。

    一旦你有了 FormClosingEventHandler , GetInvocationList 应该做这个工作。


    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);
            }
        }
    }
    
        2
  •  1
  •   SLaks    15 年前

    问题可能是表单没有验证。

    这个 FormClosing 事件由private引发 WmClose 方法在 Form ,初始化 e.Cancel !Validate(true) . 我没有调查过,但在某些情况下, Validate 会一直回来的 false ,导致关闭被取消,而不考虑任何事件处理程序。

    要调查此问题,请启用 .Net source debugging ,在您的 合拢 处理程序,转到源 Form.WmClose (向上调用堆栈),在 WMSECH ,然后再次关闭窗体。然后,在调试器中单步执行,并查看原因 验证 正在回归 . (或正在设置哪个事件处理程序) e.取消 成真)

    要解决问题,请设置 e.取消 在你自己的处理程序中。