Diskuze: c# form - dynamicky přidávané položky do kontextového menu
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 15 zpráv z 15.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
položka na kterou uživatel kliknul se ti vrátí v parametru sender obsluhy události. Takže na všechny dynamicky vytvořené položky přidej nějakou obsluhu události, které bude mít standardní parametry sender a e a pak v ni si můžeš zjistit z parametru sender o kteroru položku jde.
Tak jsem si vytvořil událost:
this.treeMenuStripItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.TreeMenuStripItemDropDownItemClicked);
Ta opravdu funguje, že když kliknu v kontextovém menu na položky: test,
aaa, bbb tak skočím do obsluhy této události. To jsem si odkrokoval.
Ale když chci přes sender zjistit na jakou položku bylo kliknuto tak sender
nabízí možnosti jen: sender.Equals, sender.GetHashCode, sender.GetType,
sender.ToString...
Díky za odpověď. Teď už mohu pracovat jako s položkou ale problém je v tom, že v senderu mám uloženou položku: Test a já jsem klikl na: aaa. Viz. obrázek v prvním příspěvku....
protože jsi tu událost nastavil na
this.treeMenuStripItem
cž je předpokládám položka Test, tu událost musíš nastavit na položku aaa, pak bbb, zkrátka na všechny na kterých to chceš odchytit.
No... Já jsem to dělával za pomocí přiřazování anonymní metody na handler při vytváření, a jako identifikátor jsem použil lokální proměnnou (třeba z foreache).
Nějak takto: (kód jsem vymyslel na rychlo, nemusí to dávat smysl)
void Populate(){
string[] names = new string[] { "A", "B", "C", "D" }; //Pole s položkama, reprezentuje třeba seznam klíčů položek
foreach(string name in names){ //Cyklus, který projde všechny položky
ToolStripItem item = new ToolStripItem(); //Nová položka
item.Text = name; //Text položky
item.Clicked = (o, e) => { //Lambda výraz, vytváříme a předáváme novou anonymní metodu
Clicked(name); //Zavoláme metodu, která se postará o kód po kliknutí, předáváme proměnnou z foreach cyklu
};
}
}
void Clicked(string text){
MessageBox.Show(text); //Zde si dělej co chceš
}
Dělával, ale nedělám.
Jednak třeba proto, že to je neefektivní, pro každou položku vytváříš
novou metodu.
Pro pár položek to nevadí, ale teď si představ, že těch položek máš
stovky. Možná nereálné, ale přece chceme, aby naše appka byla
škálovatelná, ne?
Dnes bych na to šel přes sender.
Jakmile připíchneš na událost metodu odpovídající handleru (tj. s
parametry : )
object sender, EventArgs e
...dostaneš objekt sender. Jedná se o přetypovaný objekt ovládacího
prvku, který vyvolal událost.
Tzn. jestli se kliklo na položku v menu, sender bude přetypovaný
ToolStripItem, který lze přetypovat zpět.
Toho můžeš krásně využít, protože ToolStripItem má vlastnost Key (klíč), kterou můžeš nastavit na cokoli, a pak se podle toho rozhodovat.
Nějak takto:
void Populate(){
string[] names = new string[] { "A", "B", "C", "D" }; //Pole s položkama, reprezentuje třeba seznam klíčů položek
foreach(string name in names){ //Cyklus, který projde všechny položky
ToolStripItem item = new ToolStripItem(); //Nová položka
item.Text = name; //Text položky
item.key = name; //Klíč položky (důležitý!)
item.Clicked += Clicked; //Zde připíchneme metodu na událost
}
}
void Clicked(object sender, EventArgs e){ //Jakmile se událost vyvolá...
ToolStripItem clickedItem = (ToolStripItem)o; //...můžeme si sender přetypovat na ToolStripItem.
MessageBox.Show(clickedItem.Key); //No a vypíšeme ten klíč, který jsme dříve uložili
}
Díky za odpověď.
Ale je tam:
this.treeMenuStripItem.DropDownItemClicked
a když jsem to krokoval a klikl jsem na položku "Test" tak to do té
události neskočilo až když jsem klikl na "test" nebo "aaa" nebo "bbb". Tak
ztoho jsem usoudil, že obsluhuji tyto položky.
Ale položky test, aaa, bbb jsou uživatelsky měnitelné za běhu programu.
Takže nevím kolik jich bude a vytvářet třeba 20 událostí pro každou
položku to mi nepřijde moc efektivní...
Myslel jsem, že existuje nějaká událost click pro ten list s položkami
(test, aaa, bbb), kdy bych pak zjistil na kterou položku se kliklo.
Díky za odpověď...
Tak tohle už je na mě dost složitý, ale nejefektivnější O vlastnosti key jsem vůbec
nevěděl. Zkusím to nějak střebat a dát do svého programu. Díky
Tak u
ToolStripItem item = new ToolStripItem(); //Nová položka
se objevila chybová hláška
Nelze vytvořit instanci abstraktní třídy nebo rozhraní System.Windows.Forms.ToolStripItem. (CS0144)
a ještě u
item.key = name; //Klíč položky (důležitý!)
toto
System.Windows.Forms.ToolStripItem neobsahuje definici key a nebyla nalezena žádná metoda rozšíření key, která by přijímala první argument typu System.Windows.Forms.ToolStripItem (nechybí direktiva using nebo odkaz na sestavení?) (CS1061)
Promiň, to má člověk tak, když už pomalu usíná u klávesnice.
Nahraď ToolStripItem za ToolStripMenuItem, a vlastnost Key za Tag.
Takže takto:
ToolStripMenuItem item = new ToolStripMenuItem(); //Nová položka
...
item.Tag = name; //Klíč položky (důležitý!)
...
MessageBox.Show(clickedItem.Tag); //No a vypíšeme ten klíč, který jsme dříve uložili
A slovo "klíč" by bylo vhodnější nahradit za "značku", v tomto případě.
V poho
Ještě mám jeden dotaz. Upravil jsem
item.Clicked += Clicked; //Zde připíchneme metodu na událost
na
item.Click += Clicked;
ale teď se při kliknutí na "test" nebo "aaa" nebo "bbb" v kontextovém menu nedostanu do udalosti
void Clicked(object sender, EventArgs e)
Aha.
Zdá se, že událost Click neplatí na položky které jsou podřazené, budeme
muset tedy metodu připíchnout na nadřazené menu, a tedy to bude událost
DropDownItemClicked.
Stejně tak musíme změnit metodu samotnou.
Nyní není senderem položka, ale nadřazené menu, změnil se typ argumentů,
kde následně ten objekt obsahuje položku, na kterou se kliklo.
void Populate(){
string[] names = new string[] { "A", "B", "C", "D" }; //Pole s položkama, reprezentuje třeba seznam klíčů položek
foreach(string name in names){ //Cyklus, který projde všechny položky
ToolStripMenuItem item = new ToolStripMenuItem(); //Nová položka
item.Text = name; //Text položky
item.Tag = name; //Značka položky (důležitá!)
menu.Items.Add(item); //Přidáme položku do menu
}
menu.DropDownItemClicked += Clicked; //Připíchneme metodu na událost
}
void Clicked(object sender, ToolStripItemClickedEventArgs e){ //Jakmile se událost vyvolá...
ToolStripItem clickedItem = e.ClickedItem; //...můžeme si získat položku, na kterou se kliklo.
MessageBox.Show(clickedItem.Tag); //No a vypíšeme tu značku, kterou jsme dříve uložili
}
Zobrazeno 15 zpráv z 15.