背景
我在回圈中動態創建了鏈接標簽,這些鏈接標簽是使用函式創建的,從資料庫表中獲取它的名稱。(在代碼中表示為 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.";
}
}
我想發生什么?
創建鏈接標簽時,我希望它們打開一個用戶控制元件,我嘗試撰寫一個函式。
例如
private void deck_1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
MessageBox.Show("sadadsdasdas");
panel1.Controls.Add(myUserControl);
}
這只是......不起作用,我無法弄清楚為什么,當點擊鏈接標簽時,訊息框也沒有出現。
uj5u.com熱心網友回復:
在您的理解中,您缺少的部分是當您雙擊設計器中的鏈接時會發生什么。沒有魔法;只有您通常看不到的代碼
這是一個帶有 LinkLabel 的新表單:

這是你雙擊它時得到的:

但是,希望這是燈泡時刻:

每個表單都有一個部分類,Windows 表單設計器在其中撰寫所有代碼。您將代碼寫入 Form2.cs;它寫入 Form2.Designer.cs。這樣一來,它所寫的所有冗長內容都被隱藏在視線之外(并且只能小心地手動修改,或者備份。另一個很好的理由讓它不礙事!)
因為它是一個partial類,所以 C# 在編譯時會將它們合并為一個。這就是設計師撰寫的所有代碼與您的代碼合并以做有用的事情的方式
The form designer writes this:
this.linkLabel1.LinkClicked =
new System.Windows.Forms.LinkLabelLinkClickedEventHandler(
this.linkLabel1_LinkClicked
^^^^^^^^^^^^^^^^^^^^^^^^^^^
this method is in Form2.cs
);
..and the linkLabel1_LinkClicked is the method in "your" code; there's the glue of how clicking on one of the designer's linklabels calls code that you wrote
--
Now, you're effectively doing (in your code in the question) what the designer normally does in its code; you're building a UI, positioning and sizing components etc and you're doing it programmatically. You need to wire your events up programmatically too
You can do exactly the same as the designer has done when it wired up the LinkCLicked event. Under your line:
deck_1.Size = new Size(270, 20);
You can put:
deck_1.LinkClicked = new LinkLabelLinkClickedEventHandler(deck_1_LinkClicked);
You can even shorten it a bit:
deck_1.LinkClicked = deck_1_LinkClicked;
This will connect all of your linklabels to the same handler; you can use the sender argument to work out which one was clicked.
Optionally you could give each one a different handler:
deck_1.LinkClicked = (s, e) => {
MessageBox.Show("linkLabel at Y coordinate " deck_1.Location.Y " was clicked");
panel1.Controls.Add(myUserControl);
}
This would mean that each linklabel had a different method handling the click event; (s,e) => { MessageBox.Show(...) } is a sort of miniature, nameless, method (a lambda) - it embodies the functionality you want to carry out. It's hard to advise more on what you'd want the method body of it to do because your posted example handler doesn't do anything dynamic/varying.
I put the Y into the messagebox call to demontrate how the variables you use in the loop will be captured and remembered so the code still works in 5 minutes time when it's called..
..but on that note beware - if you reference e.g. y inside the body of this handler, it won't be the value of y at the time the handler was created, it will be the value of it at the time it was executed - subtle difference that leads to obscure bugs.
//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);
}
Simple rule of thumb is "don't use, in a lambda like this, variables that have their values modified - only ever refer to variables you don't modify, or variables that are modified by making a new object for them"
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/454933.html
上一篇:帶有淡入淡出影片的影像幻燈片
