Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az ContextMenuOpening esemény kezelhető az alkalmazásban, hogy a megjelenítés előtt módosítson egy meglévő helyi menüt, vagy letiltsa az egyébként megjelenő menüt úgy, hogy a Handled tulajdonságot true az eseményadatokban. A Handled eseményadatokban true beállításának tipikus oka az, hogy a menüt teljes egészében egy új ContextMenu objektumra cseréli, ami néha megköveteli a művelet megszakítását és egy új megnyitás indítását. Ha a ContextMenuOpening esemény kezelőit írja, tisztában kell lennie az ContextMenu vezérlők és a helyi menük általános megnyitásáért és elhelyezéséért felelős szolgáltatás időzítési problémáival. Ez a témakör a helyi menü különböző nyitóforgatókönyveinek kódtechnikáit mutatja be, és egy olyan esetet mutat be, amelyben az időzítéssel kapcsolatos probléma merül fel.
A ContextMenuOpening esemény kezelésére több forgatókönyv is létezik:
A menüelemek módosítása megjelenítés előtt.
A teljes menü cseréje megjelenítés előtt.
Teljesen letiltja a meglévő helyi menüt, és nem jelenít meg helyi menüt.
példa
A menüelemek módosítása megjelenítés előtt
A meglévő menüelemek módosítása meglehetősen egyszerű, és valószínűleg ez a leggyakoribb forgatókönyv. Ezt úgy teheti meg, hogy hozzáadja vagy kivonja a helyi menü beállításait az alkalmazás aktuális állapotadataira vagy adott állapotinformációkra válaszul, amelyek a helyi menüt igénylő objektum tulajdonságaként érhetők el.
Az általános technika az, hogy lekérjük az esemény forrását, amely a jobb gombbal kattintott vezérlő, majd megszerezzük a ContextMenu tulajdonságot ebből a vezérlőből. Általában ellenőrizni szeretné a Items gyűjteményt, hogy lássa, mely helyi menüelemek vannak már a menüben, majd adja hozzá vagy távolítsa el a megfelelő új MenuItem elemeket a gyűjteménybe vagy onnan.
void AddItemToCM(object sender, ContextMenuEventArgs e)
{
//check if Item4 is already there, this will probably run more than once
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
foreach (MenuItem mi in cm.Items)
{
if ((String)mi.Header == "Item4") return;
}
MenuItem mi4 = new MenuItem();
mi4.Header = "Item4";
fe.ContextMenu.Items.Add(mi4);
}
A teljes menü cseréje megjelenítés előtt
Egy másik forgatókönyv az, ha a teljes helyi menüt szeretné lecserélni. Természetesen használhatja az előző kód egy változatát is, hogy eltávolítsa egy meglévő helyi menü minden elemét, és újakat adjon hozzá a nullától kezdve. Az összes elem helyi menüben való lecserélésének intuitívabb módja az, ha létrehozunk egy új ContextMenu-t, elemekkel feltöltjük, majd a vezérlőelem FrameworkElement.ContextMenu tulajdonságát az új ContextMenu-re állítjuk be.
Az alábbi egyszerű kezelőkód egy ContextMenucseréjéhez. A kód egy egyéni BuildMenu metódusra hivatkozik, amelyet azért választ el a rendszer, mert a példakezelők közül több is meghívja.
void HandlerForCMO(object sender, ContextMenuEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
}
ContextMenu BuildMenu()
{
ContextMenu theMenu = new ContextMenu();
MenuItem mia = new MenuItem();
mia.Header = "Item1";
MenuItem mib = new MenuItem();
mib.Header = "Item2";
MenuItem mic = new MenuItem();
mic.Header = "Item3";
theMenu.Items.Add(mia);
theMenu.Items.Add(mib);
theMenu.Items.Add(mic);
return theMenu;
}
Ha azonban ezt a stílusú kezelőt használja ContextMenuOpening, akkor valószínűleg időzítési problémát fedhet fel, ha a ContextMenu beállításához használt objektum nem rendelkezik meglévő helyi menüvel. Amikor egy felhasználó a jobb gombbal egy vezérlőelemre kattint, ContextMenuOpening akkor is létrejön, ha a meglévő ContextMenu üres vagy null értékű. Ebben az esetben azonban a forráselemen beállított új ContextMenu túl későn érkezik ahhoz, hogy megjelenjen. Ha a felhasználó másodszor is a jobb gombbal kattint, ezúttal az új ContextMenu jelenik meg, az érték nem null értékű, és a kezelő megfelelően lecseréli és megjeleníti a menüt, amikor a kezelő másodszor fut. Ez két lehetséges megoldást javasol.
Ügyeljen arra, hogy a ContextMenuOpening kezelők mindig olyan vezérlőkkel fussanak, amelyeknél legalább egy helyőrző ContextMenu álljon rendelkezésre, amelyet a kezelőkódra cserélni szándékozik. Ebben az esetben továbbra is használhatja az előző példában látható kezelőt, de általában szeretne egy helyőrzőt ContextMenu hozzárendelni a kezdeti jelöléshez.
<StackPanel> <Rectangle Fill="Yellow" Width="200" Height="100" ContextMenuOpening="HandlerForCMO"> <Rectangle.ContextMenu> <ContextMenu> <MenuItem>Initial menu; this will be replaced ...</MenuItem> </ContextMenu> </Rectangle.ContextMenu> </Rectangle> <TextBlock>Right-click the rectangle above, context menu gets replaced</TextBlock> </StackPanel>Tegyük fel, hogy a kezdeti ContextMenu érték valamilyen előzetes logika alapján null értékű lehet. Ellenőrizheti, hogy a ContextMenu értéke null, vagy egy jelző segítségével a kódban ellenőrizheti, hogy a kezelő legalább egyszer futott-e. Mivel feltételezi, hogy a ContextMenu hamarosan megjelenik, a kezelő ezután beállítja a Handled
trueaz eseményadatokban. A helyi menü megjelenítéséért felelős ContextMenuService esetében az eseményadatokban szereplőtrueHandled értéke azt jelenti, hogy a helyi menü/vezérlőelem-kombináció megjelenítésének megszakítása kérvénye, amely az eseményt kiváltotta.
Most, hogy letiltotta a vélhetően gyanús helyi menüt, a következő lépés egy új beszolgáltatása, majd annak megjelenítése. Az új beállítása lényegében ugyanolyan, mint az előző kezelőé: létrehoz egy új ContextMenu-t, és ezzel állítja be a vezérlőforrás FrameworkElement.ContextMenu tulajdonságát. A további lépés az, hogy most a helyi menü megjelenítését kell kényszerítenie, mert letiltotta az első kísérletet. A megjelenítés kényszerítéséhez állítsa a Popup.IsOpen tulajdonságot true értékre a vezérlőben. Legyen óvatos, amikor ezt teszi, mert a helyi menü megnyitása a kezelőben újra előhozahatja a ContextMenuOpening eseményt. Ha újra belép a kezelőbe, az végtelenül rekurzívvá válik. Ezért mindig ellenőriznie kell a null vagy a jelölőt, ha egy helyi menüt nyit meg egy ContextMenuOpening eseménykezelőn belül.
Meglévő helyi menü letiltása és a Nincs helyi menü megjelenítése
Az utolsó forgatókönyv, ahol egy menüt teljesen elnyomó kezelőt írni, nem gyakori. Ha egy adott vezérlőnek nem kellene helyi menüt megjelenítenie, valószínűleg több módja van ennek biztosítására, mint a menü letiltásával, amikor egy felhasználó kéri. Ha azonban a kezelővel el szeretné tiltani a helyi menüt, és nem akar semmit megjeleníteni, akkor a kezelőben egyszerűen be kell állítania a Handled-t true-re az eseményadatokban. A helyi menü megjelenítéséért felelős ContextMenuService ellenőrzi a vezérlőn létrehozott esemény eseményadatait. Ha az eseményt Handled jelölte meg az útvonal bármely pontján, akkor a helyi menüben az eseményt kezdeményező művelet el lesz tiltva.
void HandlerForCMO2(object sender, ContextMenuEventArgs e)
{
if (!FlagForCustomContextMenu)
{
e.Handled = true; //need to suppress empty menu
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
FlagForCustomContextMenu = true;
fe.ContextMenu.IsOpen = true;
}
}
}
Lásd még
.NET Desktop feedback