Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das ContextMenuOpening Ereignis kann in einer Anwendung behandelt werden, um entweder ein vorhandenes Kontextmenü vor der Anzeige anzupassen oder das Menü zu unterdrücken, das andernfalls angezeigt wird, indem die Handled Eigenschaft true in den Ereignisdaten festgelegt wird. Der typische Grund für die Einstellung von Handled auf true in den Ereignisdaten besteht darin, das Menü vollständig durch ein neues ContextMenu-Objekt zu ersetzen, was manchmal das Abbrechen des Vorgangs und das Starten eines neuen Öffnens erfordert. Wenn Sie Handler für das ContextMenuOpening-Ereignis schreiben, sollten Sie sich der Timing-Probleme im Zusammenhang mit einem ContextMenu-Steuerelement und dem Dienst bewusst sein, der für das Öffnen und Positionieren von Kontextmenüs für Steuerelemente im Allgemeinen verantwortlich ist. In diesem Thema werden einige der Codetechniken für verschiedene Kontextmenüöffnungsszenarien veranschaulicht und ein Fall veranschaulicht, in dem das Timing-Problem wiedergegeben wird.
Es gibt mehrere Szenarien für die Behandlung des ContextMenuOpening Ereignisses:
Anpassen der Menüelemente vor der Anzeige.
Ersetzen des gesamten Menüs vor der Anzeige.
Vollständiges Unterdrücken vorhandener Kontextmenüs und Anzeigen eines Kontextmenüs unterbleibt.
Beispiel
Anpassen der Menüelemente vor der Anzeige
Das Anpassen der vorhandenen Menüelemente ist relativ einfach und wahrscheinlich das häufigste Szenario. Sie können dies tun, um Kontextmenüoptionen als Reaktion auf aktuelle Statusinformationen in Ihrer Anwendung oder bestimmte Statusinformationen hinzuzufügen oder zu subtrahieren, die als Eigenschaft für das Objekt verfügbar sind, in dem das Kontextmenü angefordert wird.
Die allgemeine Technik besteht darin, die Quelle des Ereignisses abzurufen, bei dem es sich um das spezifische Steuerelement handelt, auf das mit der rechten Maustaste geklickt wurde, und die ContextMenu Eigenschaft daraus abrufen. Normalerweise möchten Sie die Items Sammlung überprüfen, um zu sehen, welche Kontextmenüelemente bereits im Menü vorhanden sind, und dann entsprechende neue MenuItem Elemente zu oder aus der Auflistung hinzufügen oder daraus entfernen.
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);
}
Ersetzen des gesamten Menüs vor der Anzeige
Ein alternatives Szenario ist, wenn Sie das gesamte Kontextmenü ersetzen möchten. Sie können natürlich auch eine Variante des vorherigen Codes verwenden, um jedes Element eines vorhandenen Kontextmenüs zu entfernen und neue elemente hinzuzufügen, die mit Element 0 beginnen. Der intuitivere Ansatz zum Ersetzen aller Elemente im Kontextmenü besteht jedoch darin, ein neues ContextMenuElement zu erstellen, es mit Elementen zu füllen und dann die FrameworkElement.ContextMenu Eigenschaft eines Steuerelements auf die neue ContextMenufestzulegen.
Im Folgenden sehen Sie den einfachen Handlercode zum Ersetzen eines ContextMenu. Der Code verweist auf eine benutzerdefinierte BuildMenu Methode, die getrennt wird, da sie von mehreren Beispielhandlern aufgerufen wird.
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;
}
Wenn Sie jedoch diesen Stil eines Handlers für ContextMenuOpening verwenden, kann möglicherweise ein Timing-Problem entstehen, wenn das Objekt, in dem Sie die ContextMenu festlegen, kein bereits vorhandenes Kontextmenü hat. Wenn ein Benutzer mit der rechten Maustaste auf ein Steuerelement klickt, wird es auch dann ausgelöst, ContextMenuOpening wenn das vorhandene ContextMenu Steuerelement leer oder null ist. In diesem Fall kommt jedoch das neue ContextMenu Element, das Sie für das Quellelement festgelegt haben, zu spät ein, um angezeigt zu werden. Wenn der Benutzer ein zweites Mal mit der rechten Maustaste klickt und dieses Mal Ihre neue ContextMenu erscheint, ist der Wert ContextMenu nicht NULL, und Ihr Handler wird das Menü ordnungsgemäß ersetzen und anzeigen, wenn der Handler ein zweites Mal ausgeführt wird. Dies schlägt zwei mögliche Problemumgehungen vor:
Stellen Sie sicher, dass ContextMenuOpening Handler immer für Steuerelemente ausgeführt werden, die mindestens einen Platzhalter ContextMenu zur Verfügung haben, den Sie durch den Handlercode ersetzen möchten. In diesem Fall können Sie den im vorherigen Beispiel gezeigten Handler weiterhin verwenden, sie möchten jedoch in der Regel einen Platzhalter ContextMenu im anfänglichen Markup zuweisen:
<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>Gehen Sie davon aus, dass der Anfangswert ContextMenu möglicherweise null ist, basierend auf einer vorläufigen Logik. Sie können entweder ContextMenu auf null überprüfen oder ein Flag in Ihrem Code verwenden, um zu prüfen, ob Ihr Handler mindestens einmal ausgeführt wurde. Da Sie davon ausgehen, dass die ContextMenu kurz davor ist angezeigt zu werden, setzt Ihr Handler Handled auf
truein den Ereignisdaten. Für das ContextMenuService, das für die Anzeige des Kontextmenüs verantwortlich ist, stellt eintrueWert in den Handled Ereignisdaten eine Anforderung dar, die Anzeige für die Kontextmenü-/Steuerelementkombination abzubrechen, die das Ereignis ausgelöst hat.
Nachdem Sie nun das potenziell verdächtige Kontextmenü unterdrückt haben, besteht der nächste Schritt darin, ein neues zu liefern und es dann anzuzeigen. Das Festlegen des neuen ist im Grunde identisch mit dem vorherigen Handler: Sie erstellen eine neue ContextMenu und legen die Eigenschaft der Steuerelementquelle FrameworkElement.ContextMenu damit fest. Der zusätzliche Schritt besteht darin, dass Sie jetzt die Anzeige des Kontextmenüs erzwingen müssen, da Sie den ersten Versuch unterdrückt haben. Um die Anzeige zu erzwingen, legen Sie die Popup.IsOpen Eigenschaft innerhalb des Handlers auf true fest. Achten Sie dabei darauf, da das Öffnen des Kontextmenüs im Handler das ContextMenuOpening Ereignis erneut auslöst. Wenn Sie den Handler erneut eingeben, wird er unendlich rekursiv. Wenn Sie ein Kontextmenü innerhalb eines null Ereignishandlers öffnen, müssen Sie daher immer auf ContextMenuOpening überprüfen oder ein Kennzeichen verwenden.
Unterdrücken aller vorhandenen Kontextmenüs und Anzeigen keines Kontextmenüs
Das letzte Szenario, das Schreiben eines Handlers, der ein Menü vollständig unterdrückt, ist ungewöhnlich. Wenn ein bestimmtes Steuerelement kein Kontextmenü anzeigen soll, gibt es wahrscheinlich geeignetere Möglichkeiten, dies zu gewährleisten, als indem das Menü nur dann unterdrückt wird, wenn ein Benutzer es anfordert. Wenn Sie jedoch den Handler verwenden möchten, um ein Kontextmenü zu unterdrücken und nichts anzuzeigen, sollte der Handler einfach Handled auf true in den Ereignisdaten setzen. Das ContextMenuService, das für die Anzeige eines Kontextmenüs verantwortlich ist, überprüft die Ereignisdaten des Ereignisses, das es auf dem Steuerelement ausgelöst hat. Wenn das Ereignis an einer beliebigen Stelle entlang der Route markiert Handled wurde, wird die geöffnete Aktion im Kontextmenü, die das Ereignis initiiert hat, unterdrückt.
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;
}
}
}
Siehe auch
.NET Desktop feedback