Vorgehensweise: Behandeln des ContextMenuOpening-EreignissesHow to: Handle the ContextMenuOpening Event

Die ContextMenuOpening -Ereignis behandelt werden, in einer Anwendung anpassen, entweder ein vorhandenes Kontext vor oder im Menü zu unterdrücken, die andernfalls durch Festlegen von angezeigt werden würden die Handled Eigenschaft true in den Ereignisdaten.The ContextMenuOpening event can be handled in an application to either adjust an existing context menu prior to display or to suppress the menu that would otherwise be displayed by setting the Handled property to true in the event data. Der Hauptgrund für die Einstellung Handled zu true in der Daten befindet, klicken Sie im Menü vollständig durch einen neuen ersetzt ContextMenu Objekt, der in einigen Fällen erfordert der Vorgang abgebrochen wird, und starten eine neue Open.The typical reason for setting Handled to true in the event data is to replace the menu entirely with a new ContextMenu object, which sometimes requires canceling the operation and starting a new open. Wenn Sie Handler für Schreiben der ContextMenuOpening -Ereignis, sollten Sie Bedenken der Probleme mit der zeitsteuerung zwischen eine ContextMenu Steuerelement und der Dienst, der für das Öffnen und die Position des Kontextmenüs für Steuerelemente in der Regel zuständig ist.If you write handlers for the ContextMenuOpening event, you should be aware of timing issues between a ContextMenu control and the service that is responsible for opening and positioning context menus for controls in general. In diesem Thema veranschaulicht einige der Codetechniken für verschiedene Szenarien öffnen Kontextmenü, und zeigt einen Fall, in dem das Problem der zeitlichen Steuerung ins Spiel kommt.This topic illustrates some of the code techniques for various context menu opening scenarios and illustrates a case where the timing issue comes into play.

Es gibt mehrere Szenarios für die Behandlung der ContextMenuOpening Ereignis:There are several scenarios for handling the ContextMenuOpening event:

  • Anpassen von die Menüelemente vor der Anzeige.Adjusting the menu items before display.

  • Ersetzen das gesamte Menü vor der Anzeige.Replacing the entire menu before display.

  • Vollständig unterdrücken vorhandenen Kontextmenü, und kein Kontextmenü angezeigt.Completely suppressing any existing context menu and displaying no context menu.

BeispielExample

Anpassen der Menüelemente vor der AnzeigeAdjusting the Menu Items Before Display

Anpassen von den vorhandenen Menüelementen ist recht einfach gehalten und ist wahrscheinlich das gängigste Szenario.Adjusting the existing menu items is fairly simple and is probably the most common scenario. Sie können hierzu um addieren oder subtrahieren Kontextmenüoptionen, die als Reaktion auf die aktuelle Zustandsinformationen in Ihrer Anwendung oder bestimmte Statusinformationen, die als Eigenschaft für das Objekt verfügbar ist, in dem das Kontextmenü angefordert wird.You might do this in order to add or subtract context menu options in response to current state information in your application or particular state information that is available as a property on the object where the context menu is requested.

Die allgemeine Vorgehensweise zum Abrufen der Quelle des Ereignisses, die das bestimmte Steuerelement geklickt wurde, und ist die ContextMenu Eigenschaft aus.The general technique is to get the source of the event, which is the specific control that was right-clicked, and get the ContextMenu property from it. In der Regel überprüfen möchten die Items -Auflistung, um festzustellen welche Kontextmenüelemente bereits vorhanden sind, klicken Sie im Menü, und klicken Sie dann hinzufügen oder entfernen entsprechende neue MenuItem von Elementen in oder aus der Auflistung.You typically want to check the Items collection to see what context menu items already exist in the menu, and then add or remove appropriate new MenuItem items to or from the collection.

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 das gesamte Menü vor der AnzeigeReplacing the Entire Menu Before Display

Eine alternative Szenario ist, wenn Sie das Kontextmenü für die gesamte ersetzen möchten.An alternative scenario is if you want to replace the entire context menu. Sie können natürlich auch verwenden eine Variation des vorherigen Codes auf jedes Element von einem vorhandenen Kontextmenü zu entfernen und Hinzufügen von neuen Element 0 (null) ab.You could of course also use a variation of the preceding code, to remove every item of an existing context menu and add new ones starting with item zero. Aber die intuitivere Ansatz zum Ersetzen aller Elemente im Kontextmenü zum Erstellen eines neuen ContextMenumit Elementen zu füllen, und legen Sie dann die FrameworkElement.ContextMenu Eigenschaft eines Steuerelements auf das neue ContextMenu.But the more intuitive approach for replacing all items in the context menu is to create a new ContextMenu, populate it with items, and then set the FrameworkElement.ContextMenu property of a control to be the new ContextMenu.

Im folgenden ist der einfache Handler-Code zum Ersetzen einer ContextMenu.The following is the simple handler code for replacing a ContextMenu. Der Code verweist auf eine benutzerdefinierte BuildMenu -Methode, die getrennt ist, da sie aufgerufen wird von mehr als einer der Beispiel-Handler.The code references a custom BuildMenu method, which is separated out because it is called by more than one of the example handlers.

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;
}

Allerdings bei Verwendung von diese Art der Handler für ContextMenuOpening, Sie können möglicherweise ein Problem der zeitlichen Steuerung bereitstellen, wenn das Objekt, das Sie, in dem Festlegen die ContextMenu verfügt nicht über einen bereits vorhandenen Kontextmenü.However, if you use this style of handler for ContextMenuOpening, you can potentially expose a timing issue if the object where you are setting the ContextMenu does not have a preexisting context menu. Wenn ein Benutzer ein Steuerelement, mit der rechten Maustaste ContextMenuOpening wird ausgelöst, selbst wenn die vorhandene ContextMenu ist leer oder null.When a user right-clicks a control, ContextMenuOpening is raised even if the existing ContextMenu is empty or null. Aber in diesem Fall alle neuen ContextMenu Sie festlegen, auf dem Quellcomputer Element zu spät empfangen, um angezeigt zu werden.But in this case, whatever new ContextMenu you set on the source element arrives too late to be displayed. Auch wenn der Benutzer wird der rechten Maustaste ein zweites Mal auf dieses Mal die neue ContextMenu angezeigt wird, der Wert nicht Null ist, und Ihre Handler ordnungsgemäß ersetzen und klicken Sie im Menü angezeigt, wenn der Handler für ein zweites Mal ausgeführt wird.Also, if the user happens to right-click a second time, this time your new ContextMenu appears, the value is non null, and your handler will properly replace and display the menu when the handler runs a second time. Dies deutet darauf hin, zwei mögliche problemumgehungen:This suggests two possible workarounds:

  1. Stellen Sie sicher, die ContextMenuOpening Handler, die immer für Steuerelemente, die über mindestens einen Platzhalter ausführen ContextMenu verfügbar ist, die mit dem Ereignishandlercode ersetzt werden sollen.Insure that ContextMenuOpening handlers always run against controls that have at least a placeholder ContextMenu available, which you intend to be replaced by the handler code. In diesem Fall können Sie trotzdem den Handler, der im vorherigen Beispiel gezeigt verwenden, aber Sie möchten in der Regel weisen Sie einen Platzhalter ContextMenu im anfänglichen Markup:In this case, you can still use the handler shown in the previous example, but you typically want to assign a placeholder ContextMenu in the initial markup:

    <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>
    
  2. Vorausgesetzt, dass der ursprüngliche ContextMenu Wert kann null sein, basierend auf einer vorläufigen Logik.Assume that the initial ContextMenu value might be null, based on some preliminary logic. Sie können entweder ContextMenu für Null oder ein Flag in Ihrem Code zu überprüfen, ob der Handler wurde mindestens einmal ausgeführt.You could either check ContextMenu for null, or use a flag in your code to check whether your handler has been run at least once. Da Sie davon ausgehen, dass die ContextMenu geht es um werden angezeigt, den Handler an und legt dann Handled zu true in den Ereignisdaten.Because you assume that the ContextMenu is about to be displayed, your handler then sets Handled to true in the event data. Auf der ContextMenuService , die verantwortlich für die Anzeige im Menü Kontext ist eine true Wert für Handled in dieser Daten eine Anforderung zum Abbrechen der Anzeige für das Kontextmenü / zum Steuerelement-Kombination, die das Ereignis ausgelöst hat darstellt.To the ContextMenuService that is responsible for context menu display, a true value for Handled in the event data represents a request to cancel the display for the context menu / control combination that raised the event.

Nun, da Sie das Kontextmenü für die potenziell verdächtige unterdrückt haben, ist der nächste Schritt, geben Sie eine neue Methode, klicken Sie dann anzuzeigen.Now that you have suppressed the potentially suspect context menu, the next step is to supply a new one, then display it. Einrichten der neuen im Grunde identisch mit der vorherigen Handler: Sie erstellen ein neues ContextMenu und legen Sie die Steuerelement-Quelle FrameworkElement.ContextMenu Eigenschaft mit.Setting the new one is basically the same as the previous handler: you build a new ContextMenu and set the control source's FrameworkElement.ContextMenu property with it. Der zusätzliche Schritt ist, dass Sie jetzt die Anzeige des Kontextmenüs, erzwingen müssen, da Sie beim ersten Versuch unterdrückt.The additional step is that you must now force the display of the context menu, because you suppressed the first attempt. Um die Anzeige zu erzwingen, legen Sie die Popup.IsOpen Eigenschaft true im Ereignishandler.To force the display, you set the Popup.IsOpen property to true within the handler. Seien Sie vorsichtig, wenn Sie dies tun, da löst aus, öffnen das Kontextmenü im Handler der ContextMenuOpening Ereignis wird erneut.Be careful when you do this, because opening the context menu in the handler raises the ContextMenuOpening event again. Wenn Sie Ihren Handler erneut eingeben, wird er endlos rekursiv.If you reenter your handler, it becomes infinitely recursive. Aus diesem Grund Sie immer zu prüfen müssen, ist null , oder verwenden Sie ein Flag, wenn Sie ein Kontextmenü öffnen, die sich innerhalb einer ContextMenuOpening -Ereignishandler.This is why you always need to check for null or use a flag if you open a context menu from within a ContextMenuOpening event handler.

Unterdrücken vorhandenen Kontextmenü, und kein Kontextmenü angezeigtSuppressing Any Existing Context Menu and Displaying No Context Menu

Das letzte Szenario, schreiben einen Handler, der ein Menü völlig unterdrückt ist ungewöhnlich.The final scenario, writing a handler that suppresses a menu totally, is uncommon. Wenn ein bestimmtes Steuerelement kein Kontextmenü angezeigt werden soll, sind wahrscheinlich besser Möglichkeiten zum gewährleisten dies durch das Menü unterdrücken, sondern nur, wenn ein Benutzer es anfordert.If a given control is not supposed to display a context menu, there are probably more appropriate ways to assure this than by suppressing the menu just when a user requests it. Aber wenn Sie den Handler So unterdrücken ein Kontextmenü, und zeigen nichts verwenden möchten, legen Sie Ihr Handler sollte einfach Handled zu true in den Ereignisdaten.But if you want to use the handler to suppress a context menu and show nothing, then your handler should simply set Handled to true in the event data. Die ContextMenuService , verantwortlich ist, für das Anzeigen eines Kontextmenüs die Ereignisdaten des Ereignisses überprüft, es auf dem Steuerelement ausgelöst.The ContextMenuService that is responsible for displaying a context menu will check the event data of the event it raised on the control. Wenn das Ereignis markiert wurde Handled an einer beliebigen Stelle entlang der Route, klicken Sie dann die Aktion des Öffnens Kontextmenüs, die das Ereignis initiiert hat unterdrückt wird.If the event was marked Handled anywhere along the route, then the context menu open action that initiated the event is suppressed.

    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 auchSee also