Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den ContextMenuOpening händelsen kan hanteras i ett program för att antingen justera en befintlig snabbmeny innan den visas eller för att utelämna menyn som annars skulle visas genom att ange egenskapen Handled till true i händelsedata. Den typiska orsaken till att ställa in Handled till true i händelsedata är att helt ersätta menyn med ett nytt ContextMenu objekt, vilket ibland kräver att åtgärden avbryts och en ny öppning startas. Om du skriver hanterare för händelsen ContextMenuOpening bör du vara medveten om tidsproblem mellan en kontroll för ContextMenu och tjänsten som ansvarar för att öppna och placera snabbmenyer för kontroller i allmänhet. Det här avsnittet illustrerar några av kodteknikerna för olika scenarier för snabbmenyöppning och illustrerar ett fall där tidsproblemet spelar in.
Det finns flera scenarier för att hantera ContextMenuOpening händelse:
Justera menyalternativen innan de visas.
Ersätter hela menyn innan den visas.
Utelämnar alla befintliga snabbmenyer helt och visar ingen snabbmeny.
Exempel
Justera menyalternativen före visning
Att justera de befintliga menyalternativen är ganska enkelt och är förmodligen det vanligaste scenariot. Du kan göra detta för att lägga till eller subtrahera snabbmenyalternativ som svar på aktuell tillståndsinformation i ditt program eller viss tillståndsinformation som är tillgänglig som en egenskap på objektet där snabbmenyn begärs.
Den allmänna tekniken är att hämta källan till händelsen, vilket är den specifika kontroll som högerklickades och hämta egenskapen ContextMenu från den. Du vill vanligtvis kontrollera Items samling för att se vilka snabbmenyobjekt som redan finns i menyn och sedan lägga till eller ta bort lämpliga nya MenuItem objekt i eller från samlingen.
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);
}
Ersätta hela menyn före visning
Ett alternativt scenario är om du vill ersätta hela snabbmenyn. Du kan naturligtvis också använda en variant av föregående kod för att ta bort varje objekt i en befintlig snabbmeny och lägga till nya som börjar med objekt noll. Men den mer intuitiva metoden för att ersätta alla objekt i snabbmenyn är att skapa en ny ContextMenu, fylla i den med objekt och sedan ange egenskapen FrameworkElement.ContextMenu för en kontroll som den nya ContextMenu.
Följande är den enkla hanteringskoden för att ersätta en ContextMenu. Koden refererar till en anpassad BuildMenu-metod, som avgränsas eftersom den anropas av mer än en av exempelhanterarna.
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;
}
Men om du använder den här hanteraren för ContextMenuOpeningkan du potentiellt exponera ett tidsfel om objektet där du anger ContextMenu inte har någon befintlig snabbmeny. När en användare högerklickar på en kontroll utlöses ContextMenuOpening även om den befintliga ContextMenu är tom eller null. Men i det här fallet kommer det nya ContextMenu som du ställer in på källelementet för sent att visas. Om användaren råkar högerklicka en andra gång visas den här gången din nya ContextMenu och värdet är inte null, vilket gör att hanteraren korrekt ersätter och visar menyn vid det andra tillfället. Detta tyder på två möjliga lösningar:
Försäkra dig om att ContextMenuOpening-hanterare alltid körs mot kontroller som har minst en platshållare ContextMenu tillgänglig, som du tänker ersätta med hanteringskoden. I det här fallet kan du fortfarande använda hanteraren som visas i föregående exempel, men du vill vanligtvis tilldela en platshållare ContextMenu i den första 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>Anta att det inledande ContextMenu-värdet kan vara null, baserat på viss preliminär logik. Du kan antingen kontrollera ContextMenu för null eller använda en flagga i koden för att kontrollera om hanteraren har körts minst en gång. Eftersom du antar att ContextMenu är på väg att visas anger hanteraren sedan Handled till
truei händelsedata. Till ContextMenuService som ansvarar för snabbmenyvisning representerar etttruevärde för Handled i händelsedata en begäran om att avbryta visningen för snabbmenyn/kontrollkombinationen som aktiverade händelsen.
Nu när du har utelämnat den potentiellt misstänkta snabbmenyn är nästa steg att ange en ny och sedan visa den. Att ange den nya är i princip samma som den tidigare hanteraren: du skapar en ny ContextMenu och anger kontrollkällans FrameworkElement.ContextMenu egenskap med den. Det ytterligare steget är att du nu måste framtvinga visningen av snabbmenyn eftersom du undertryckte det första försöket. Om du vill framtvinga visningen anger du egenskapen Popup.IsOpen till true i hanteraren. Var försiktig när du gör detta, eftersom om du öppnar snabbmenyn i hanteraren genereras ContextMenuOpening händelsen igen. Om du använder hanteraren igen blir den oändligt rekursiv. Därför måste du alltid söka efter null eller använda en flagga om du öppnar en snabbmeny inifrån en ContextMenuOpening händelsehanterare.
Ignorera alla befintliga snabbmenyer och visa ingen snabbmeny
Det sista scenariot, att skriva en hanterare som undertrycker en meny helt, är ovanligt. Om en viss kontroll inte ska visa en snabbmeny finns det förmodligen lämpligare sätt att säkerställa detta än genom att ignorera menyn precis när en användare begär den. Men om du vill använda hanteraren för att utelämna en snabbmeny och inte visa någonting, bör hanteraren helt enkelt ange Handled till true i händelsedata. Den ContextMenuService som ansvarar för att visa en snabbmeny kommer att kontrollera händelsedatan för den händelse den utlöste på kontrollen. Om händelsen har markerats Handled någonstans längs rutten ignoreras öppna-snabbbmeny-åtgärden som initierade händelsen.
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;
}
}
}
Se även
.NET Desktop feedback