TOC

This article has been localized into German by the community.

Einfache Steuerelemente:

Das WPF Menu Steuerelement

Eines der gebräuchlichsten Teile einer Windows-Anwendung ist das Menü, das teils auch als "Hauptmenü" bezeichnet wird, da für gewöhlich nur ein einziges in der Anwendung existiert. Das Menü ist praktisch, weil es auf geringem Platz viele Optionen bietet und obwohl Microsoft das Menüband als einen Ersatz für das gute alte Menü und Symbolleisten darstellt, gehören beide definitiv immer noch zum Handwerkszeug jedes guten Entwicklers.

Zu WPF gehört ein feines Steuerelement für das Erstellen von Menüs... das Menu. Das Hinzufügen von Elementen zu diesem gestaltet sich sehr einfach - Man fügt ihm einfach ein MenuItem hinzu. Jedes MenuItem kann eine Reihe von Unterelementen besitzen, was erlaubt hierarchische Menüs zu erstellen, wie man sie aus vielen Windows-Anwendungen kennt. Lass uns gleich zu einem Beispiel übergehen, in dem wir das Menu nutzen:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuSample" Height="200" Width="200">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_New" />
                <MenuItem Header="_Open" />
                <MenuItem Header="_Save" />
                <Separator />
                <MenuItem Header="_Exit" />
            </MenuItem>
        </Menu>
        <TextBox AcceptsReturn="True" />
    </DockPanel>
</Window>

Wie in den meisten Windows-Anwendungen ist mein Menü im oberen Teil des Fensters angesiedelt. Allerdings kann man, getreu der enormen Flexibilität von WPF, ein Menu-Steuerelement platzieren wo man will und das in jeder Breite oder Höhe, die man sich wünschen kann.

Ich habe ein einziges in der obersten Ebene liegendes Element mit 4 Kind-Elementen und einem Trenner definiert. Ich nutze die Header-Eigenschaft, um die Beschriftung des Elements zu definieren. Dir sollte außerdem der Unterstrich vor dem Anfangsbuchstaben jeder Beschriftung aufgefallen sein. Es weist WPF an, den Buchstaben als ZugriffstastenInfo zu verwenden, das heißt der Nutzer kann die Alt-Taste und nachfolgend einen weiteren Buchstaben drücken, um das zugehörige Menüelement zu aktivieren. Das funktioniert für die gesamte Hierarchie, also nicht nur beim obersten Element, sondern auch allen darunter liegenden. Das heißt, in diesem Beispiel könnte ich Alt, dann F und dann N drücken, um das New-Element zu aktivieren.

Symbole und Checkboxen

Zwei charakteristische Merkmale eines Menüelements sind das Symbol, durch das das Menüelement und sein Zweck leichter identifiziert werden kann und die Fähigkeit, ankreuzbare Menüeinträge zu haben, mit denen jeweils eine bestimmte Funktion ein- und ausgeschaltet werden kann. Das WPF MenuItem unterstützt beide Merkmale und ist dabei sehr leicht zu verwenden:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuIconCheckableSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuIconCheckableSample" Height="150" Width="300">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_Exit" />
            </MenuItem>
            <MenuItem Header="_Tools">
                <MenuItem Header="_Manage users">
                    <MenuItem.Icon>
                        <Image Source="/WpfTutorialSamples;component/Images/user.png" />
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="_Show groups" IsCheckable="True" IsChecked="True" />
            </MenuItem>
        </Menu>
        <TextBox AcceptsReturn="True" />
    </DockPanel>
</Window>

Für dieses Beispiel habe ich einen zweiten Menüleisteneintrag erstellt, zu dem ich zwei Elemente hinzugefügt habe: Eines mit einem Symbol, definiert in dessen Icon-Eigenschaft, der ein normales Image-Steuerelement zugewiesen ist und eines, in dem ich die IsCheckable-Eigenschaft nutze, um dem Nutzer das Markieren und Abwählen des Eintrags zu ermöglichen. Darüber hinaus nutze ich die IsChecked-Eigenschaft, um die Markierung standardmäßig zu setzen. Im Code-behind kann die gleiche Eigenschaft gelesen werden, um zu ermitteln, ob ein Menüeintrag an- oder abgewählt ist.

Behandeln von Mausklicks

Wenn der Nutzer auf ein Menüelement klickt, möchte man für gewöhnlich ein Ereignis auslösen. Der einfachste Weg, das zu bewerkstelligen, ist einfach einen Click-Eventhandler zum Menüelement hinzuzufügen, in etwa so:

<MenuItem Header="_New" Click="mnuNew_Click" />

Im Code-behind muss man dann die mnuNew_Click-Methode implementieren, in etwa so:

private void mnuNew_Click(object sender, RoutedEventArgs e)
{
	MessageBox.Show("New");
}

Das genügt für einfachere Anwendungen oder Prototypen, aber der WPF-konforme Weg ist, ein Command dafür zu verwenden.

Tastenkürzel und Befehle

Man kann ein Click-Event einfach behandeln, wie wir es oben getan haben, aber die verbreitetere Vorgehensweise ist die Nutzung von WPF-Befehlen (Commands). Es gibt viel zu sagen über das Benutzen und Erstellen von Befehlen, deshalb haben sie auf dieser Seite auch ihren eigenen Bereich, aber für's Erste kann ich dir sagen, dass sie in WPF einige Vorteile bieten, besonders in Kombination mit einer Menü- oder Symbolleiste.

Zum einem stellen sie sicher, dass man die gleiche Aktion mit einer Symbolleiste, einem Menü und sogar einem Kontextmenü verknüpfen kann, ohne dafür den gleichen Code an mehreren Stellen implementieren zu müssen. Zum anderen vereinfachen sie das Behandeln von Tastenkürzeln deutlich. Im Gegensatz zu WinForms registriert WPF nicht automatisch Listener ("Zuhörer") für Tastenkürzel wenn man sie z.B. einem Menüelement zuweist - Man muss dies von Hand machen.

Wenn man dagegen Commands nutzt, wird WPF hellhörig und reagiert automatisch auf Tastenkürzel. Der Text (Header) des Menüelements wird ebenfalls automatisch zugewiesen (man kann es bei Bedarf überschreiben), genauso wie der InputGestureText, der dem Nutzer zeigt, welches Tastenkürzel für das Aufrufen des jeweiligen Menüelements verwendet werden kann. Lass uns zu einem Beispiel übergehen, in dem das Menü mit WPF-Commands verbunden wird:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuWithCommandsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuWithCommandsSample" Height="200" Width="300">
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="NewCommand_CanExecute" Executed="NewCommand_Executed" />
    </Window.CommandBindings>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Command="New" />
                <Separator />
                <MenuItem Header="_Exit" />
            </MenuItem>
            <MenuItem Header="_Edit">
                <MenuItem Command="Cut" />
                <MenuItem Command="Copy" />
                <MenuItem Command="Paste" />
            </MenuItem>
        </Menu>

        <TextBox AcceptsReturn="True" Name="txtEditor" />
    </DockPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Input;

namespace WpfTutorialSamples.Common_interface_controls
{
	public partial class MenuWithCommandsSample : Window
	{
		public MenuWithCommandsSample()
		{
			InitializeComponent();
		}

		private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			txtEditor.Text = "";
		}
	}
}

Es mag nicht offensichtlich sein, aber durch die Verwendung von Commands bekommen wir eine Reihe von Dingen gratis: Tastenkürzel, Beschriftungen und InputGestureText für die Menüpunkte, zudem aktiviert/deaktiviert WPF automatisch die Menüpunkte in Abhängigkeit vom aktiven Steuerelement und seinem Zustand. In diesem Fall sind Ausschneiden und Kopieren deaktiviert weil kein Text ausgewählt ist, aber Einfügen ist aktiviert, weil meine Zwischenablage nicht leer ist!

Und weil WPF weiß, wie bestimmte Befehle in Kombination mit speziellen Bedienelementen zu handhaben sind, in diesem Fall die Ausschneiden-/Kopieren-/Einfügen-Befehle und ein Texteingabefeld, müssen wir nicht einmal ihre Executed-Events behandeln - Sie funktionieren sofort! Wir müssen sie allerdings für das New-Command behandeln, da WPF nicht weiß, was wir von ihm wollen, wenn der Nutzer es aktiviert. Dies wird mit den CommandBindings des Fenster erreicht, die im Detail im Kapitel über Commands erklärt sind.

Zusammenfassung

Die Arbeit mit dem WPF Menu ist zugleich einfach und schnell, wodurch es einfach wird, sogar komplexe Menü-Hierarchien zu erstellen. Wenn diese mit WPF-Commands verbunden werden, erhält man darüber hinaus sehr viel Funktionalität gratis dazu.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!