【问题标题】:Loop through all controls on form and if event exists on control add handler to control循环遍历表单上的所有控件,如果控件上存在事件,则将处理程序添加到控件
【发布时间】:2016-06-24 14:19:28
【问题描述】:

我期望它如何工作的伪代码,但我不确定我需要调用哪些 .net 方法来完成此操作。

    Dim specifiedEvent = "MouseDown"
    Dim handler = handler
    For Each control As Control in form.controls
      If control has specifiedEvent Then

        control.specifiedEvent addhandler handler

      End If 
    Next

c#是链接的,因为它可以很容易地转换成vb

【问题讨论】:

  • 虽然您可以使用反射来查找指定的事件,但这里的问题是指定处理程序代码。您希望处理程序看起来如何?不同的事件可以有不同的参数。
  • @MatthewWatson in .net 我认为处理程序必须根据他们正在处理的事件有一个特定的定义。所以我希望它在这种情况下对 mousedown 有适当的定义,因为我正在搜索 mousedown。
  • 这只是为了MouseDown吗?每个Control 都有一个MouseDown 事件......无需检查。
  • 您想知道该事件是否存在于类中,或者是否挂钩在一个实例中?

标签: c# .net vb.net winforms reflection


【解决方案1】:

我不太擅长 VB,所以这里我的 C# 尝试:

foreach(Control c in form.Controls)
    c.GetType().GetEvent(specifiedEvent)?.AddMethod?.Invoke(c, new object[] {handler});

Type.GetEvent() 为具有指定名称的事件返回 EventInfo,如果不存在此类事件,则返回 null

EventInfoAddMethod 属性是该事件的add 方法的MethodInfo

这是 C# 6。因此您可能需要添加额外的 null 检查(我使用空传播/空条件运算符 ?)来检查事件是否真的存在。


如果您的问题只是关于MouseDown 事件,那就有点奇怪了,因为Control 类本身声明了MouseDown 事件。所以从Control 继承的每个 类都有这个事件(除了你处理故意隐藏这个事件的类)。所以你可以简单地将事件添加到所有Controls:

foreach(Control c in form.Controls)
    c.MouseDown += handler;

【讨论】:

  • 我是偏执狂还是有人在追捕我?这是今天第三次我在没有解释其他广受欢迎的答案的情况下投了反对票...
  • 发生这种情况时很烦人。人们至少应该给出一个解释(除非问题很明显——这里不是这样)。
  • 我要给出的答案与您对每个具有MouseDown 事件的控件的评论相同。我不是反对者,但也许这是更好的答案?我打算回答,但复制您的评论毫无意义。
  • 请注意,EventInfo 类型中没有名为 AddMethod() 的方法。你的意思是放别的东西吗?
  • @MatthewWatson 没有方法AddMethod(),它是MethodInfo 类型的属性。这是将处理程序添加到事件的方法MethodInfo
【解决方案2】:

正如人们已经指出的那样,如果您只是在寻找“MouseDown”,则无需检查。

但是,如果您需要一种使用反射的方法,该方法将给定处理程序的名称和事件名称作为字符串将处理程序附加到事件,那么您可以这样做。

此代码将事件处理程序附加到嵌套在容器控件中的每个控件,其中包含与提供的名称匹配的事件:

public void HookUp(Control container, string handlerName, string eventName)
{
    MethodInfo eventHandler = this.GetType().GetMethod(handlerName, BindingFlags.NonPublic | BindingFlags.Instance);

    foreach (var control in container.Controls.Cast<Control>())
    {
        var ev = control.GetType().GetEvent(eventName);

        if (ev == null)
            continue;

        var d = Delegate.CreateDelegate(ev.EventHandlerType, this, eventHandler);
        ev.AddEventHandler(control, d);
    }
}

例如,您的鼠标按下处理程序如下所示:

private void mouseEventHandler(object sender, MouseEventArgs e)
{
    Debug.WriteLine(e.Button);
}

您可以像这样从适当的位置(例如 Form 构造函数)调用它:

public Form1()
{
    InitializeComponent();
    HookUp(this, "mouseEventHandler", "MouseDown");
}

注意以下几点:

  1. 这似乎是一件奇怪的事情。我觉得会有更好的方法来解决您的问题(听起来像是 X-Y 问题)。
  2. 这不会取消订阅该事件。您必须在表单的 dispose 方法中使用类似的代码来执行此操作,而只调用 .RemoveEventHandler()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多