Avatar
Michaal.K
Člen
Avatar
Michaal.K:

Ahoj,

vytvořil jsem si kontextové menu a jeho položky přidávám v kódu. Problém je v tom, že počet položek v kontextovém menu se uživatelsky mění za běhu programu a já potřebuju zjistit na kterou položku uživatel kliknul a podle toho zavolat dannou funkci. Viz. obrázek. Díky za rady...

 
Odpovědět 17. srpna 12:46
Avatar
Odpovídá na Michaal.K
Michal Žůrek (misaz):

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.

Editováno 17. srpna 12:51
Nahoru Odpovědět  +1 17. srpna 12:49
Nesnáším {}, proto se jim vyhýbám.
Avatar
Michaal.K
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
Michaal.K:

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...

 
Nahoru Odpovědět 17. srpna 14:03
Avatar
hj.masek
Člen
Avatar
hj.masek:
var clickedItem = sender as ToolStripItem;
//ostatni operace uz s polozkou
 
Nahoru Odpovědět 17. srpna 14:40
Avatar
Michaal.K
Člen
Avatar
Odpovídá na hj.masek
Michaal.K:

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....

 
Nahoru Odpovědět 17. srpna 14:58
Avatar
Odpovídá na Michaal.K
Michal Žůrek (misaz):

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.

Nahoru Odpovědět 17. srpna 18:00
Nesnáším {}, proto se jim vyhýbám.
Avatar
VitekST
Člen
Avatar
Odpovídá na Michaal.K
VitekST:

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
}
 
Nahoru Odpovědět 17. srpna 21:01
Avatar
Michaal.K
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
Michaal.K:

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.

 
Nahoru Odpovědět 18. srpna 7:41
Avatar
Michaal.K
Člen
Avatar
Odpovídá na VitekST
Michaal.K:

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

 
Nahoru Odpovědět 18. srpna 7:46
Avatar
Michaal.K
Člen
Avatar
Odpovídá na VitekST
Michaal.K:

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)
 
Nahoru Odpovědět 18. srpna 8:38
Avatar
VitekST
Člen
Avatar
Odpovídá na Michaal.K
VitekST:

Promiň, to má člověk tak, když už pomalu usíná u klávesnice. :D

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ě.

Editováno 18. srpna 8:48
 
Nahoru Odpovědět 18. srpna 8:46
Avatar
Michaal.K
Člen
Avatar
Odpovídá na VitekST
Michaal.K:

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)
 
Nahoru Odpovědět 18. srpna 9:01
Avatar
VitekST
Člen
Avatar
Odpovídá na Michaal.K
VitekST:

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 DropDownItemClic­ked.

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
}
Akceptované řešení
+20 Zkušeností
Řešení problému
 
Nahoru Odpovědět 18. srpna 9:12
Avatar
Michaal.K
Člen
Avatar
Odpovídá na VitekST
Michaal.K:

Díky moc :-) Teď už vše funguje správně....

 
Nahoru Odpovědět 18. srpna 11:18
Avatar
VitekST
Člen
Avatar
 
Nahoru Odpovědět 18. srpna 11:22
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 15 zpráv z 15.