Label of UserControl is hiding MouseEnter event

拥有回忆 提交于 2020-06-17 00:08:24

问题


I can't active the event mouse enter because label's on top. I try assign the same event, but when I call MyUserControl myUserControl = (MyUserControl)sender; results in error. Here's my code:

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;
}

the event (Form_MouseEnter) works when it occurs in the form, but in the components it returns an error like 'System.InvalidCastException'

public partial class MyUserControl : UserControl
{
    int g_intCodEquip;
    public int Codigo
    {
        set { g_intCodEquip = value; }
        get { return g_intCodEquip; }
    }
}

回答1:


To ensure that any and all child controls of MyUserControl will be correctly handled, we can iterate the control tree of MyUserControl and subscribe to the MouseEnter event.

We route all of these events to a centralized Any_MouseEnter handler which in turn fires a new custom event that the Form1 subscribes to:

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;
}

Note: This is a follow-up question to your previous post so I copied over the 'Codigo' property.

OK, so now in the main Form1, we subscribe to the new event fired by MyUserControl. Now the sender is type MyUserControl, the cast succeeds, and the notification works no matter which control the mouse enters.

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

As a test runner, we can set up a 4 x 3 array of MyUserControl (the working example MyUserControl contains both a Label and a 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);
        }
    }
}

The behavior follows this 10-second clip.




回答2:


Change your code to a safe cast.

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

Here you can find the documentation: https://docs.microsoft.com/en-us/dotnet/csharp/how-to/safely-cast-using-pattern-matching-is-and-as-operators

Side note:

You have showed us the registration of the event handler MyUserControl_MouseEnter but provided the code for Form_MouseEnter.




回答3:


The error occurs here at this line:

MyUserControl myUC = (MyUserControl)sender;

...since you wired up the Labels to also run that code, but in those cases the sender variable will be a Label which cannot be cast to MyUserControl.

You could simply grab the .Parent property which should be the usercontrol since you only went one level deep when you originally wired them up. Just check to see if sender is not the MyUserControl type first:

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


来源:https://stackoverflow.com/questions/62174390/label-of-usercontrol-is-hiding-mouseenter-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!