TOC

This article is currently in the process of being translated into Russian (~99% done).

Общие элементы управления:

Элемент 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 командами, вы получаете так много функциональности бесплатно.

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!