【问题标题】:Watch control to determine events being fired?监视控制以确定被触发的事件?
【发布时间】:2010-10-16 15:36:34
【问题描述】:

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

【问题讨论】:

    标签: c# winforms events


    【解决方案1】:

    您可以使用反射,但由于涉及到各种事件处理程序签名,它会有点棘手。基本上,您必须为类型中的每个事件获取EventInfo,并在调用AddEventHandler 之前使用EventHandlerType 属性确定要创建的委托类型。 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);
                }
            }
        }
    }
    

    【讨论】:

    • 正是我想要的!看来我需要认真阅读和修补反思。谢谢!
    • 确实很有帮助。谢谢。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这是无法做到的。如果您使用 Reflector 查看大量框架的类,您会发现触发事件时的常见模式:

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

      因此,如果没有人订阅该事件,甚至不会触发该事件

      【讨论】:

      • 我不明白为什么这意味着它无法完成 - 它只是意味着需要订阅该事件。这与在代码中显式订阅每个事件有很大的不同。
      • 我认为你在分裂头发。通过创建硬编码委托或使用反射,您仍然“显式”添加事件处理程序。我的回答假设他根本不想订阅这些事件(即使通过反射),但想以其他方式查看事件序列。
      猜你喜欢
      • 2013-08-14
      • 2019-06-20
      • 2021-07-11
      • 1970-01-01
      • 2019-03-22
      • 2012-12-24
      • 2020-12-09
      • 2021-12-30
      • 1970-01-01
      相关资源
      最近更新 更多