如何为 link 标签设置事件监听器?

How to set Event Listener for a link label?

背景

我在循环中动态创建了链接标签,它是使用函数创建的,从数据库表中获取它的名称。 (代码中表示为users_decks)

我检查了其他问题,他们大多写了一个函数,就像我最后要说的那样,但那些并没有奏效。

但我一直在苦苦思索如何为这些链接标签设置事件监听器,比如在设计器中点击它们两次?

代码

private void create_Dynamic_label_Texts()
        {
            try
            {
                int x = 130;
                int y = 35;
                foreach (var deck in Deck_Owner.users_decks)
                {
                    LinkLabel deck_1 = new LinkLabel();
                    deck_1.Text = " " + deck;
                    deck_1.LinkBehavior = LinkBehavior.NeverUnderline;
                    deck_1.LinkVisited = false;
                    deck_1.AutoSize = false;
                    deck_1.BackColor = Color.LightGray;
                    deck_1.LinkColor = Color.Black;
                    deck_1.Location = new Point(x, y);
                    deck_1.Size = new Size(270, 20);
                    Controls.Add(deck_1);
                    deck_1.Show();
                    y = y + 24;
                }
            }
            catch
            {
                lblNoDeck.Text = "You haven't created decks yet! Create some to start.";
            }
        }

我希望发生什么?

创建Link标签时,我想让它们打开一个用户控件,我试过写一个函数。

例如

private void deck_1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
    MessageBox.Show("sadadsdasdas");
    panel1.Controls.Add(myUserControl);
}

这只是......不起作用,我无法弄清楚为什么,单击链接标签时也不会出现消息框。

根据您的理解,您遗漏的部分是当您双击设计器中的 link 时会发生什么。没有魔法;只有您通常看不到的代码

这是一个带有 LinkLabel 的新表单:

这是双击它时得到的结果:

但是,希望这是灵光一闪的时刻:

每个表单都有一个部分 class,windows 表单设计者在其中编写所有代码。你把你的代码写成 Form2.cs;它写入 Form2.Designer.cs。这样一来,它所写的所有冗长内容都被隐藏起来了(而且它只应该小心地手动修改,或者备份..另一个让它远离的好理由!)

因为是partialclass,所以C#在编译的时候把它们合二为一了。这就是设计师编写的所有代码如何与您的代码合并以做有用的事情

表单设计者这样写:

this.linkLabel1.LinkClicked +=  
  new System.Windows.Forms.LinkLabelLinkClickedEventHandler(
     this.linkLabel1_LinkClicked
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     this method is in Form2.cs
);
                                                     

..linkLabel1_LinkClicked 是“your”代码中的方法;点击设计师的 link 标签之一会调用您编写的代码

--

现在,您(在您的问题代码中)有效地做了设计者通常在其代码中做的事情;您正在构建一个 UI、定位和调整组件大小等,并且您正在以编程方式进行。您也需要以编程方式连接您的事件

您可以执行与设计器在连接 LinkCLicked 事件时所做的完全相同的操作。你的线下:

deck_1.Size = new Size(270, 20);
                

您可以输入:

deck_1.LinkClicked += new LinkLabelLinkClickedEventHandler(deck_1_LinkClicked);

你甚至可以缩短一点:

deck_1.LinkClicked += deck_1_LinkClicked;
                

这会将所有 link 标签连接到同一个处理程序;您可以使用 sender 参数计算出点击了哪一个。

您可以选择给每个人一个不同的处理程序:

deck_1.LinkClicked += (s, e) => {
    MessageBox.Show("linkLabel at Y coordinate " + deck_1.Location.Y + " was clicked");
    panel1.Controls.Add(myUserControl);
}

这意味着每个 link标签都有不同的方法来处理点击事件; (s,e) => { MessageBox.Show(...) } 是一种微型的、无名的方法(lambda)——它体现了您要执行的功能。很难就您希望它的方法主体执行的操作提供更多建议,因为您发布的示例处理程序没有执行任何操作 dynamic/varying.

我将 Y 放入消息框调用中,以演示如何捕获和记住您在循环中使用的变量,以便代码在调用时在 5 分钟内仍然有效..

..但要注意这一点 - 如果您引用例如y 在此处理程序的主体内,它不会是创建处理程序时 y 的值,而是它在 时的值已执行 - 导致模糊错误的细微差别。

//beware! this messagebox shows 275 for every linklabel, if there are 10 labels, because 275 is the resting value of a loop that does 35 + (10 * 24)
deck_1.LinkClicked += (s, e) => {
    MessageBox.Show("linkLabel at Y coordinate " + y + " was clicked");
    panel1.Controls.Add(myUserControl);
}

简单的经验法则是“不要在像这样的 lambda 中使用修改了值的变量 - 仅引用您不修改的变量,或通过 new 对象