UserControl 的标签隐藏了 MouseEnter 事件

Label of UserControl is hiding MouseEnter event

我无法激活鼠标输入事件,因为标签在顶部。我尝试分配相同的事件,但是当我调用 MyUserControl myUserControl = (MyUserControl)sender;结果出错。这是我的代码:

foreach (Control ctrl in MyUserControl.Controls)
{
     ctrl.MouseEnter += MyUserControl_MouseEnter;
}    

private void MyUserControl_MouseEnter(object sender, EventArgs e)
{
   MyUserControl myUC = (MyUserControl)sender;
   int test = myUC .Codigo;
}

事件 (Form_MouseEnter) 在表单中发生时有效,但在组件中它 returns 像 'System.InvalidCastException'

这样的错误
public partial class MyUserControl : UserControl
{
    int g_intCodEquip;
    public int Codigo
    {
        set { g_intCodEquip = value; }
        get { return g_intCodEquip; }
    }
}

为确保正确处理 MyUserControl 的所有子控件,我们可以迭代 MyUserControl 的控件树并订阅 MouseEnter 事件。

我们将所有这些事件路由到一个集中式 Any_MouseEnter 处理程序,该处理程序依次触发 Form1 订阅的新 custom 事件:

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        IterateControlTree();
    }

    void IterateControlTree(Control control = null)
    {
        if (control == null)
        {
            control = this;
        }
        control.MouseEnter += Any_MouseEnter;
        foreach (Control child in control.Controls)
        {
            IterateControlTree(child);
        }
    }

    private void Any_MouseEnter(object sender, EventArgs e)
    {
        // Before calling Invoke we need to make sure that
        // MyUserControlMouseEnter is not null as would be
        // the case if there are no subscribers to the event.
        // The '?' syntax performs this important check.
        MyUserControlMouseEnter?.Invoke(this, EventArgs.Empty);
    }

    // A custom event that this custom control can fire.
    public event EventHandler MyUserControlMouseEnter;

    public int Codigo
    {
        set
        {
            test = value;
        }
        get
        {
            return test;
        }
    }
    int test = 0;
}

注意:这是的后续问题所以我复制了'Codigo' 属性.

好的,现在在主 Form1 中,我们订阅了 MyUserControl 触发的新事件。现在发件人类型MyUserControl,转换成功,无论鼠标进入哪个控件,通知都有效。

private void MyUserControl_MouseEnter(object sender, EventArgs e)
{
    MyUserControl myUserControl = (MyUserControl)sender;
    Debug.WriteLine(
        "MouseEnter Detected: " + myUserControl.Name + 
        " - Value of Codigo is: " + myUserControl.Codigo);
}

作为测试运行器,我们可以设置一个 4 x 3 的 MyUserControl 数组(working example MyUserControl 包含一个 Label 和一个 Button)。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    TableLayoutPanel tableLayoutPanel1 = new TableLayoutPanel() { ColumnCount = 4, RowCount = 4, Dock = DockStyle.Fill };
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        Controls.Add(tableLayoutPanel1);
        int row, column;
        for (int count = 0; count < 12; count++)
        {
            row = count / 4; column = count % 4;

            MyUserControl myUserControl = new MyUserControl();
            myUserControl.Name = "MyUserControl_" + count.ToString("D2"); // Name it! (Default is "") 

            // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv  
            // Subscribe to custom event fired by MyUserControl             
            myUserControl.MyUserControlMouseEnter += MyUserControl_MouseEnter;
            // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        

            myUserControl.Codigo = 1000 + count;                         // Example to set Codigo

            tableLayoutPanel1.Controls.Add(myUserControl, column, row);
        }
    }
}

行为遵循此 10-second 剪辑。

将您的代码更改为安全转换。

private void Form_MouseEnter(object sender, EventArgs e)
{
    if (sender is MyUserControl myUC)
    {
        int test = myUC.Codigo;
    }
}

您可以在此处找到文档:https://docs.microsoft.com/en-us/dotnet/csharp/how-to/safely-cast-using-pattern-matching-is-and-as-operators

旁注:

您向我们展示了事件处理程序的注册 MyUserControl_MouseEnter,但提供了 Form_MouseEnter 的代码。

错误发生在这一行:

MyUserControl myUC = (MyUserControl)sender;

...因为您将标签也连接到 运行 该代码,但在那些情况下,sender 变量将是无法转换为 MyUserControl 的标签。

您可以简单地获取 .Parent 属性,它应该是用户控件,因为您最初连接它们时只深入了一层。首先检查 sender 是否不是 MyUserControl 类型:

MyUserControl myUC;
if (sender is MyUserControl)
{
    myUC = (MyUserControl)sender;
}
else
{
    myUC = (MyUserControl)((Control)sender.Parent);
}