【问题标题】:How to list all events a Winforms control has published如何列出 Winforms 控件已发布的所有事件
【发布时间】:2021-07-08 07:16:46
【问题描述】:
    private List<EventInfo> GetAllTheEventsTheControlCanPublish(Control control)
    {
        return control.GetType().GetEvents().ToList();
    }

问题是:如何仅获取控件已发布的事件列表? 我有一个简单的 winform 应用程序:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace GettingAllEventsOfAControl
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            _listOfSelectableValues = new List<int>() { 3, 5, 8, 11, 15 };
            foreach (int currentValue in _listOfSelectableValues)
            {
                 comboBox1.Items.Add(currentValue);
            }

            comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_SelectedIndexChanged);
            comboBox1.Click += new EventHandler(comboBox1_Click);            

        _allTheEventsTheControlCanPublish = GetAllTheEventsTheControlCanPublish(comboBox1);
    }

    private List<int> _listOfSelectableValues;
    private List<EventInfo> _allTheEventsTheControlCanPublish;

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {

    }

    private void comboBox1_Click(object sender, EventArgs e)
    {

    }

    private List<EventInfo> GetAllTheEventsTheControlCanPublish(Control control)
    {
        return control.GetType().GetEvents().ToList();
    }
}

}

我想要一个类似的方法:

    private List<EventInfo> GetPublishedEvents(Control control)
    {
        return ...;
    }

在这种情况下将返回一个包含 2 个项目的列表:

  1. SelectedIndex 已更改
  2. 点击

即使 dr.null 让步了,我的问题仍然有效:
给定一个控件,有没有办法获取仅包含该控件实际发布的事件的 EventInfo 类型的对象列表?

以不同的形式提出问题:
GetPublishedEvents(Control control) 方法返回特定控件可以发布的所有事件的 EventInfo 类型的对象列表。
如果相应的控件实际发布了此特定事件,是否有对象 EventInfo 的字段或属性的值发生更改?
然后,我可以遍历列表 allTheEventsTheControlCanPublish 中的所有对象并检查此字段或属性的值,从而找出实际发布了哪些事件。

【问题讨论】:

  • Some useful info here 以及为什么很难获得您想要的列表。你能解释一下你想做什么吗?也许还有其他方法。
  • 在我删除控件之前,我必须取消它订阅的所有事件。 你确定吗?为什么?
  • @TaW 根据docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/…:以编程方式从集合中删除控件 从事件中删除事件处理程序。在 Visual Basic 中,使用 RemoveHandler 语句关键字;在 C# 中,使用 -= 运算符。使用 Remove 方法从面板的 Controls 集合中删除所需的控件。调用Dispose方法释放控件使用的所有资源。
  • 那么就-=+=你自己。就这么简单。
  • 这不是一个答案,而是一个评论,只是为了在我回答之前看看你是否能理解并且你投反对票,因为也许你不明白。编译和运行完美。您可以使用 Visual Studio 的帮助来确定您需要的内容。如果需要,请说明您的 .NET 版本和 C# 编译器版本。

标签: c# visual-studio-2010 events


【解决方案1】:

大部分这些东西是故意对程序员隐藏的,所以如果你只是为了代码的正确性和确保没有内存泄漏而这样做,你可能太努力了。

C# 是一种托管语言,因此通常添加处置、垃圾收集或尝试管理内存对您不利,因为您会妨碍 C# 处理此问题的流线型流程,并且您添加的代码可以被未来的 C# 更新所破坏。

通过该免责声明,您可以从继承链 MyComboBox -> ComboBox -> ListControl -> Control -> Component 中闯入 Component 的受保护“Events”变量。这个变量是受保护的,这意味着它只能被自己和孩子访问。因此,如果我们创建一个 ComboBox 的子项:'myComboBox',我们就可以在那里访问它。

public class myCombobox : ComboBox
{
  public EventHandlerList GetPublishedEvents()
  {
    return Events;
  }
}

Events 将只包含已发布的 EventHandlers,但每个事件处理程序的密钥都是秘密,因此它们不会被弄乱。没有被这个吓倒,我写了一个函数来处理控件的所有事件。

public class myCombobox : ComboBox
{
  public void removeAllActiveEventHandlers()
  {
    Events.Dispose();
  }
}

-= 事件的结果以及在创建和销毁 1000 个组合框后处理事件与仅在销毁对象后让 C# 处理它没有区别。

此外,在调试模式下运行,在诊断工具下,拍摄内存使用快照,查看对象,然后 EventHandler Count 显示 C# 在所有情况下都销毁了所有 2000 个事件。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace GettingAllEventsOfAControl
{
  public partial class Form1 : Form
  {
    public class myCombobox : ComboBox
    {
      public EventHandlerList GetPublishedEvents()
      {
        return Events;
      }

      public void removeAllActiveEventHandlers()
      {
        Events.Dispose();
      }
    }

    public Form1()
    {
      InitializeComponent();
    }
        
    public void generateComboBox(string name)
    {
      // 
      // comboBox1
      // 
      myCombobox comboBox1 = new myCombobox();

      comboBox1.FormattingEnabled = true;
      comboBox1.Location = new System.Drawing.Point(442, 121);
      comboBox1.Name = "comboBox2";
      comboBox1.Size = new System.Drawing.Size(187, 21);
      comboBox1.TabIndex = 0;
      Controls.Add(comboBox1);


      _listOfSelectableValues = new List<int>() { 3, 5, 8, 11, 15 };
      foreach (int currentValue in _listOfSelectableValues)
      {
        comboBox1.Items.Add(currentValue);
      }

      comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_SelectedIndexChanged);
      comboBox1.Click += new EventHandler(comboBox1_Click);

      _allTheEventsTheControlCanPublish = GetAllTheEventsTheControlCanPublish(comboBox1);
      var allEvents = comboBox1.GetPublishedEvents();

      // Removed via -=
      comboBox1.SelectedIndexChanged -= new EventHandler(comboBox1_SelectedIndexChanged);
      comboBox1.Click -= new EventHandler(comboBox1_Click);

      // Removed via dispose()
      comboBox1.removeAllActiveEventHandlers();      

      Controls.Remove(comboBox1);

      comboBox1.Dispose(); // <- also does nothing
    }

    private List<int> _listOfSelectableValues;
    private List<EventInfo> _allTheEventsTheControlCanPublish;

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { }
    private void comboBox1_Click(object sender, EventArgs e) { }

    private List<EventInfo> GetAllTheEventsTheControlCanPublish(Control control)
    {
      return control.GetType().GetEvents().ToList();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      for (int i = 0; i < 1000; i++)
      {
        generateComboBox("comboBox" + i);
      }

      // V Used for testing only.  I would never use these two lines in my real code.
      System.GC.Collect();
      GC.WaitForPendingFinalizers();

      MessageBox.Show("Done", "Hi Done");
    }
  }
}

干杯!

【讨论】:

  • 感谢您的回答。尽管它的名字很有希望,但 EventHandlerList GetPublishedEvents() 方法返回 myComboBox 类的所有内置事件的 EventHandlerList 类型项目的集合,而不仅仅是 2 个已发布的事件 SelectedIndexChanged 和 Click,所以你的回复没有回答我问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 2012-12-30
相关资源
最近更新 更多