观察控制以确定被触发的事件?

时间:2009-03-31 16:05:28

标签: c# winforms events

是否有办法列出特定WinForms控件的所有触发事件,而无需为每个可能的事件显式创建处理程序?例如,我可能希望在各种数据绑定操作期间看到在DataGridView和BindingSource之间触发的事件序列。

3 个答案:

答案 0 :(得分:8)

你可以使用反射,但由于涉及各种事件处理程序签名,它会有点棘手。基本上,您必须为类型中的每个事件获取EventInfo,并在调用EventHandlerType之前使用AddEventHandler属性来计算要创建的委托类型。 Delegate.CreateDelegate适用于遵循正常事件处理程序模式的所有内容,但是......

这是一个示例应用。请注意,它没有进行任何检查 - 如果您使用“非标准”事件给它一些东西,它将抛出异常。你也可以很容易地使用反射打印出事件参数。

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;

namespace ConsoleApp
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Form form = new Form { Size = new Size(400, 200) };
            Button button = new Button { Text = "Click me" };
            form.Controls.Add(button);
            EventSubscriber.SubscribeAll(button);
            Application.Run(form);
        }
    }

    class EventSubscriber
    {
        private static readonly MethodInfo HandleMethod = 
            typeof(EventSubscriber)
                .GetMethod("HandleEvent", 
                           BindingFlags.Instance | 
                           BindingFlags.NonPublic);

        private readonly EventInfo evt;

        private EventSubscriber(EventInfo evt)
        {
            this.evt = evt;
        }

        private void HandleEvent(object sender, EventArgs args)
        {
            Console.WriteLine("Event {0} fired", evt.Name);
        }

        private void Subscribe(object target)
        {
            Delegate handler = Delegate.CreateDelegate(
                evt.EventHandlerType, this, HandleMethod);
            evt.AddEventHandler(target, handler);
        }

        public static void SubscribeAll(object target)
        {
            foreach (EventInfo evt in target.GetType().GetEvents())
            {
                EventSubscriber subscriber = new EventSubscriber(evt);
                subscriber.Subscribe(target);
            }
        }
    }
}

答案 1 :(得分:1)

我认为你可以使用Reflection来做到这一点。

答案 2 :(得分:0)

这不可能。如果你使用Reflector查看很多Framework的类,你会在触发事件时找到一个共同的模式:

// fire event
if (EventDelegate != null)
   EventDelegate(eventArgs);

因此,如果没有人订阅它,事件甚至都不会被解雇