动态用户控件中的控件被点击时,单击事件未触发。

6
我有许多控件在我的用户控件中。并且动态地在我的表单中加载用户控件。
UserControl2 usercontrol = new UserControl2();
usercontrol.Tag = i;
usercontrol.Click += usercontrol_Click;
flowLayoutPanel1.Controls.Add(usercontrol);

private void usercontrol_Click(object sender, EventArgs e)
{
   // handle event
}

当我点击用户控件中的某个控件时,单击事件不会触发。只有当我点击用户控件的空白区域时才触发。


你的UserControl中有哪些控件?你是不是想让UserControl中的任何东西被点击时都触发主控件的点击事件? - Idle_Mind
图片框和文本框。是的,从用户控件的任何位置点击。 :) - Karlx Swanovski
5个回答

17

通过递归所有控件并将每个控件的Click()事件连接到同一个处理程序。从那里调用InvokeOnClick()。现在点击任何东西都会触发主UserControl的Click()事件:

public partial class UserControl2 : UserControl
{

    public UserControl2()
    {
        InitializeComponent();
        WireAllControls(this);
    }

    private void WireAllControls(Control cont)
    {
        foreach (Control ctl in cont.Controls)
        {
            ctl.Click += ctl_Click;
            if (ctl.HasChildren)
            {
                WireAllControls(ctl);
            }
        }
    }

    private void ctl_Click(object sender, EventArgs e)
    {
        this.InvokeOnClick(this, EventArgs.Empty); 
    }

}

1
那是什么原因呢?为什么事件没有自然触发? - flaudre
2
@Flaudre,因为子控件都有自己的点击事件触发。在这里,我们告诉这些点击处理程序引发主用户控件的点击事件,以便(大概)主用户控件的容器/父级可以执行某些操作。这会使用户控件看起来像一个“可点击单元”。但是,如果单击各个控件应该执行不同的操作,则不应这样做。 - Idle_Mind
1
@andypopa,不过只会在UserControl实例化时将它们连接一次。你有多少个控件能够注意到这很“慢”?!...你有什么替代方案的答案? - Idle_Mind
1
1000+。我有一个自定义控件,里面有20多个控件(它需要表示一个联系人:有一个用于FirstName的标签,一个用于包含FirstName实际值的标签等等)。我为每个数据库条目创建此控件。我的替代答案不是你的方法错了,我认为我/每个遇到这个性能问题的人都做错了。我理解在这种情况下应该只是绘制而不是向用户控件添加控件。编辑:如果您对我有更好的解决方案,我也在听:D - andypopa
1
@andypopa,忽略“太多控件”的问题,如果您不需要为标签捕获鼠标事件,则可以从Label继承并在WndProc()中为WM_NCHITTEST消息返回HTTRANSPARENT。现在鼠标将“穿过”标签并命中父容器(UserControl)。您需要更改UserControl以使用Label控件而不是原始控件。这可以通过直接编辑设计师文件来完成。有关详细信息,请参见此SO答案 - Idle_Mind
显示剩余2条评论

1
这应该可以解决你的问题。
//Event Handler for dynamic controls
usercontrol.Click += new EventHandler(usercontrol_Click); 

0

看这里:

this.btnApply.Click += new System.EventHandler(this.btnApply_Click);


0

因为来自ChildControls的事件不会传播到父级。所以您必须在每个添加到UserControl的子控件上处理Click事件。


0

1-在命名空间中定义一个委托

public delegate void NavigationClick(int Code, string Title);

在UserControl类中从您的委托定义一个事件:

        public  event NavigationClick navigationClick;

在UserControl中为您的控件事件编写以下代码:

private void btn_first_Click(object sender, EventArgs e)
    {
        navigationClick(101, "First");
    }

在您的 Windows Form 中,然后在您的 UserControl 上使用以下代码:

private void dataBaseNavigation1_navigationClick(int Code, string Title)
    {
        MessageBox.Show(Code + " " + Title);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接