Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De ContextMenuOpening gebeurtenis kan worden verwerkt in een toepassing om een bestaand contextmenu aan te passen voordat deze wordt weergegeven of om het menu te onderdrukken dat anders zou worden weergegeven door de Handled eigenschap true in te stellen op de gebeurtenisgegevens. De gebruikelijke reden voor het instellen van Handled naar true in de gebeurtenisgegevens is om het menu volledig te vervangen door een nieuw ContextMenu object, wat soms vereist dat de bewerking wordt geannuleerd en een nieuwe opening wordt gestart. Als u handlers schrijft voor de ContextMenuOpening gebeurtenis, moet u rekening houden met tijdsproblemen tussen een ContextMenu besturingselement en de service die verantwoordelijk is voor het openen en positioneren van contextmenu's voor besturingselementen in het algemeen. Dit onderwerp illustreert enkele van de codetechnieken voor verschillende scenario's voor het openen van contextmenu's en illustreert een geval waarin het timingprobleem aan de orde komt.
Er zijn verschillende scenario's voor het afhandelen van de ContextMenuOpening gebeurtenis:
Pas de menu-items aan voordat deze worden weergegeven.
Het hele menu vervangen voordat het wordt weergegeven.
Volledig onderdrukken van een bestaand contextmenu en geen contextmenu weergeven.
Voorbeeld
De menu-items aanpassen voordat deze worden weergegeven
Het aanpassen van de bestaande menu-items is redelijk eenvoudig en is waarschijnlijk het meest voorkomende scenario. U kunt dit doen om contextmenuopties toe te voegen of af te trekken als reactie op de huidige statusgegevens in uw toepassing of bepaalde statusgegevens die beschikbaar zijn als eigenschap in het object waar het contextmenu wordt aangevraagd.
De algemene techniek is het ophalen van de bron van de gebeurtenis. Dit is het specifieke besturingselement waarop met de rechtermuisknop is geklikt en de ContextMenu eigenschap ervan ophalen. Meestal wilt u de Items verzameling controleren om te zien welke contextmenu-items er al bestaan in het menu en vervolgens de juiste nieuwe MenuItem items aan of uit de verzameling toevoegen of verwijderen.
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);
}
Het hele menu vervangen voordat het wordt weergegeven
Een alternatief scenario is als u het hele contextmenu wilt vervangen. U kunt natuurlijk ook een variant van de voorgaande code gebruiken om elk item van een bestaand contextmenu te verwijderen en nieuwe items toe te voegen die beginnen met item nul. Maar de meer intuïtieve benadering voor het vervangen van alle items in het contextmenu is door een nieuw ContextMenu te maken, deze met items te vullen, en vervolgens de FrameworkElement.ContextMenu-eigenschap van een bedieningselement in te stellen op het nieuwe ContextMenu.
Hier volgt de eenvoudige handlercode voor het vervangen van een ContextMenu. De code verwijst naar een aangepaste BuildMenu methode, die wordt gescheiden omdat deze wordt aangeroepen door meer dan een van de voorbeeldhandlers.
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;
}
Als u echter deze stijl van handler voor ContextMenuOpening gebruikt, kunt u mogelijk een timingprobleem tegenkomen als het object waarin u ContextMenu instelt geen bestaand contextmenu heeft. Wanneer een gebruiker met de rechtermuisknop op een controle klikt, wordt ContextMenuOpening geactiveerd, zelfs als het bestaande ContextMenu leeg of null is. Maar in dit geval komt elke nieuwe ContextMenu die je op het bronelement instelt te laat om te worden weergegeven. Als de gebruiker een tweede keer met de rechtermuisknop klikt, verschijnt deze keer uw nieuwe ContextMenu, is de waarde niet null en zal uw handler het menu correct vervangen en weergeven wanneer de handler een tweede keer wordt uitgevoerd. Dit stelt twee mogelijke tijdelijke oplossingen voor:
Zorg ervoor dat ContextMenuOpening handlers altijd worden uitgevoerd op bedieningselementen die ten minste een tijdelijke aanduiding ContextMenu beschikbaar hebben, die u wilt vervangen door de handlercode. In dit geval kunt u nog steeds de handler gebruiken die in het vorige voorbeeld wordt weergegeven, maar meestal wilt u een tijdelijke aanduiding ContextMenu toewijzen in de eerste markering:
<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>Stel dat de initiële ContextMenu waarde null kan zijn, op basis van een bepaalde voorlopige logica. U kunt controleren op ContextMenu null of een vlag in uw code gebruiken om te controleren of uw handler ten minste één keer is uitgevoerd. Omdat u ervan uitgaat dat het ContextMenu wordt weergegeven, stelt uw handler vervolgens Handled in op
truein de gebeurtenisgegevens. Voor het contextmenu dat verantwoordelijk is voor de weergave, vertegenwoordigt een ContextMenuService waarde voortruein de gebeurtenisgegevens een verzoek om de weergave van de combinatie van het contextmenu en het besturingselement dat de gebeurtenis heeft gegenereerd, te annuleren.
Nu u het potentieel verdachte contextmenu hebt onderdrukt, is de volgende stap het aanmaken van een nieuw contextmenu en deze weergeven. U stelt de nieuwe in op vrijwel dezelfde manier als bij de vorige handler: u bouwt een nieuwe ContextMenu en gebruikt deze om de eigenschap FrameworkElement.ContextMenu van de besturingselementenbron in te stellen. De extra stap is dat u nu de weergave van het contextmenu moet afdwingen, omdat u de eerste poging hebt onderdrukt. Om de weergave af te dwingen, stelt u binnen de handler de eigenschap Popup.IsOpen in op true. Wees voorzichtig wanneer u dit doet, omdat het openen van het contextmenu in de handler de ContextMenuOpening gebeurtenis opnieuw genereert. Als u de handler opnieuw opgeeft, wordt deze oneindig recursief. Daarom moet u altijd controleren op null of een vlag gebruiken als u een contextmenu opent vanuit een ContextMenuOpening evenementverwerker.
Bestaande contextmenu onderdrukken en geen contextmenu weergeven
Het laatste scenario, het schrijven van een handler die een menu volledig onderdrukt, is ongebruikelijk. Als een bepaald besturingselement geen contextmenu moet weergeven, zijn er waarschijnlijk meer geschikte manieren om dit te verzekeren dan door het menu te onderdrukken net wanneer een gebruiker dit aanvraagt. Maar als u de handler wilt gebruiken om een contextmenu te onderdrukken en niets weer te geven, moet uw handler eenvoudig Handled naar true instellen in de gebeurtenisgegevens. Het element ContextMenuService dat verantwoordelijk is voor het weergeven van een contextmenu controleert de gegevens van het evenement dat het in het besturingselement heeft gegenereerd. Als de gebeurtenis ergens in de route is gemarkeerd Handled , wordt de geopende actie in het contextmenu waarmee de gebeurtenis is gestart onderdrukt.
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;
}
}
}
Zie ook
- ContextMenu
- FrameworkElement.ContextMenu
- Overzicht Basiselementen
- Overzicht ContextMenu
.NET Desktop feedback