This article has been localized into Russian by the community.
Элемент Menu
Одной из общих частей UI приложения Windows является меню, иногда оно упоминается как "Главное меню", так как обычно оно существует только одно в приложении. Это очень полезный элемент интерфейса, так как предоставляет множество интересных механизмов, занимает мало места, и несмотря на то, что Windows в последнее время лоббирует использование Ribbon, старое доброе меню и панель инструментов все еще остаются на вооружении у множества разработчиков.
В WPF для создания Меню используется, как это ни странно...элемент Menu. Добавление элементов в меню это очень просто - Вы просто добавляете MenuItem, который в свою очередь может иметь множество дочерних MenuItem, позволяющих создать меню-иерархию, с которой Вы наверняка уже знакомы, после работы с приложениями Windows. Давайте, сразу начнем изучать пример использования этого элемента.
<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>
Как и в большинстве приложений Windows, мое меню размещено наверху, но учитывая колосальную гибкость WPF, Вы можете разместить меню где угодно, выбрать для него любую ширину и высоту.
Я определил один элемент верхнего уровня с четырьмя дочерними элементами и разделитель. Я использовал свойство Header для создания оглавления с названием пункта меню и имейте ввиду, что в каждом элементе меню, перед первым символом его названия необходимо вставлять нижнее подчеркивание. Оно сообщит WPF о необходимости использования сочетания клавиш (нажмите Alt и Вы увидите как появятся подсказки с первыми символами элементов меню). Этот механизм работает сверху-вниз по иерархии меню, например: запустите текущий пример и нажмите поочередно Alt, потом F и N, для активации элемента меню New.
Иконки и CheckBox'ы
Это два распространенных механизма: добавление иконки к элементу меню, для лучшей его идентификации и возможность отметить элемент меню, что позволит включить либо выключить определенный механизм (работает как элемент CheckBox). Меню в WPF поддерживает обе эти фишки, и их очень легко подключить:
<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>
Для этого примера я создал второй элемент первого уровня, в котором добавил два элемента: один с иконкой, определенной с помощью свойства Icon и стандартного элемента Image внутри нее, и второй, с использованием свойства IsCheckable, которое делает элемент двухпозиционным. Я даже использовал по умолчанию значение true этого свойства IsChecked, чтобы элемент был "включен" сразу. Это же свойство Вы можете "прочитать" из Code-Behind, чтобы знать, включен или нет данный элемент меню.
Обработка нажатий на клавиши мыши
Обычно, Вы хотите, чтобы в приложении что-то произошло при нажатии пользователем на элемент меню. Самый простой метод добавить обработчик событий к элементу меню приведен ниже:
<MenuItem Header="_New" Click="mnuNew_Click" />
В CodeBehind Вам необходимо будет следующим образом заимплементировать метод mnuNew_Click:
private void mnuNew_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("New");
}
Этого будет достаточно для большинства простых приложений или для прототипирования чего-либо, но в WPF для этого предусмотрено использование Command (команды).
Горячие клавиши и Команды
Обработать событие Click на элементе меню можно без проблем так, как мы сделали это выше, но есть способ получше - команды WPF. О том, как их создавать и использовать, полно информации, и на нашем сайте об этом тоже есть отдельная статья, поэтому здесь я только упомяну о паре преимуществ команд WPF, особенно для Menu или Toolbar.
Первое - одну и ту же реализацию команды можно использовать многократно - в панели инструментов, обычном или контекстном меню. Второе - с помощью такой команды гораздо проще обрабатывать нажатия горячих клавиш, так как WPF, в отличие от WinForms, не активирует автоматическое ожидание их нажатия при назначении клавиатурной комбинации, например, на элемент меню - так что этим следует заняться вручную.
Но вот если использовать команды, то тогда WPF сам со всей готовностью будет ожидать нажатия горячих клавиш и реагировать на них. Текст элемента меню (Header) тоже установится автоматически (хотя его, конечно, можно переопределить), аналогично - InputGestureText, отображающий пользователю доступное клавиатурное сочетание для конкретного элемента меню. А теперь - пример с использованием команд WPF в Menu:
<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 = "";
}
}
}
Может, это и не слишком очевидно, но использование команд предоставляет целую пачку плюшек: клавиатурные сокращения, отображаемый текст элемента меню (Header) и его клавиатурного сокращения (InputGestureText), кроме того WPF автоматически включит/выключит элементы меню в зависимости от активного элемента интерфейса и его состояния. Так, при текущем использовании этого примера Cut (Вырезать) и Copy (Скопировать) отключены, потому что нет выделенного текста, но зато включен Paste (Вставить), так как в моем буфере обмена текст есть.
А так как WPF в курсе, как взаимодействуют определенные команды с конкретными элементами интерфейса, то для наших Cut/Copy/Paste при их использовании с полем ввода текста даже не пришлось реализовывать события Execute - всё и так работает "из коробки". Хотя пришлось - для команды New, потому как WPF понятия не имеет, что именно мы планируем делать, когда пользователь её запустит. Для этого нужно воспользоваться CommandBindings свойством Window - подробные разъяснения в статье о командах.
Заключение
Работать с WPF Menu и легко и быстро, делая простым создание даже сложных иерархий меню, и затем комбинируя с WPF командами, вы получаете так много функциональности бесплатно.