Я слишком склонен к Windows.Forms & gulp VB 6, поэтому я вроде согласен с Джонатаном и Jase , что должно бытьболее простой / процедурный метод для статической привязки обработчиков событий, которые не обязательно CommandBindings
.И я думаю, что есть.
Хороший учебник по использованию не CommandBinding
обработчиков, подобных этому, но с акцентом на кнопки, можно найти в этом сообщении в блоге MSDN , яверить.Я отыщу и нацелусь на MenuItem
s ...
Создание ICommand
Сначала создайте класс, реализующий ICommand
.Конечно, вы можете поместить это где угодно, даже в свой файл MainWindow.xaml.cs, если хотите, чтобы демонстрационный код был безумно простым.Возможно, вы захотите сделать CanExecute
более сложным, когда захотите отключить / включить / отключить пункты меню позже, но сейчас у нас всегда будут включены наши пункты меню.
public class HelloWorldCommand : ICommand
{
public void Execute(object parameter)
{
MessageBox.Show(@"""Hello, world!"" from "
+ (parameter ?? "somewhere secret").ToString());
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
КакУчебное пособие подчеркивает, что вы можете вызывать эту команду уже из любого места, с кодом вроде ...
var hwc = new HelloWorldCommand();
if (hwc.CanExecute(this))
hwc.Execute(this);
Объявление вашей команды в окне
Так что давайте добавим своего рода "объявление"«для HelloWorldCommand
нашего окна, чтобы мы могли использовать его позже.Внутри ваших Window
тегов зарегистрируйте команду как ресурс:
<Window.Resources>
<local:HelloWorldCommand x:Key="hwc"/>
</Window.Resources>
Теперь у нас есть удобный ярлык для ссылки на эту команду «локально с пространством имен», "hwc"
, хотя вы, очевидно, можете использовать любуюСтрока, которую вы хотите.Мы будем часто использовать это в нашем xaml.
Подключение (и повторное использование!) Команды
Давайте добавим наши MenuItem
s в наш xaml.Я заменил фондовую Grid
на DockPanel
, потому что это самый простой способ (для меня) иметь равноотстоящие виджеты, которые заполняют Window
, хотя я оставил весь остальной пользовательский интерфейс.
Обратите внимание на Command="{StaticResource hwc}"
s, добавленные в каждую MenuItem
декларацию.Ключ hwc
там - помните, что это наш ярлык для HelloWorldCommand
, который мы установили на уровне Window
.И, конечно же, StaticResource
говорит просто посмотреть на ресурсы Window
.Мы ничего не связываем;мы просто используем наш ярлык.
<DockPanel LastChildFill="True">
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem
Header="_Open"
Command="{StaticResource hwc}"
>
<MenuItem.CommandParameter>
<!-- so you could make this object as complex as you wanted,
like, say, your entire Window. See magic incantation, below. -->
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}" />
</MenuItem.CommandParameter>
</MenuItem>
<MenuItem
Header="_Close"
Command="{StaticResource hwc}"
CommandParameter="Close"
InputGestureText="Ctrl+G" />
<MenuItem
Header="_Save"
Command="{StaticResource hwc}"
CommandParameter="Save" />
<Separator />
<MenuItem
Header="_Quit"
Command="{StaticResource hwc}"
CommandParameter="Quit" />
</MenuItem>
</DockPanel>
CommandParameters, чтобы различать источники событий
Обратите внимание, что мы используем одну и ту же команду для всего! Но как мы можемскажите какой виджет скинул событие?Для этого вам нужно использовать CommandParameter
- запомните сигнатуру нашего метода Execute
: Execute(object parameter)
.Этот параметр CommandParameter
- это то, что мы можем использовать, чтобы знать, как обрабатывать событие.Попробуйте выполнить это и обратите внимание, что MessageBox
будет использовать все, что есть в CommandParameter
, чтобы сообщить вам источник события.Мы делаем все вручную, но это не так уж и плохо.
Также обратите внимание, что вы можете сделать эти объекты настолько сложными, насколько захотите.Вы можете использовать свойство в теге MenuItem
для определения параметра или использовать «настоящие» теги <MenuItem.CommandParameter>
, как в пункте меню Open выше, для определения чего-то сложного.В этом случае мы передаем весь родительский Window
объект , что было самым простым (хотя и не самым чистым) способом бросить наш контекст VB6-ish в обработчик событийcode.
Добавление сочетаний клавиш к MenuItem
s (он же «Ответ на OP»)
И теперь мы наконец можем ответить на исходный вопрос!Наконец, подключим сочетание клавиш для пункта меню Close
.Вы заметите, что мы уже объявили InputGestureText
.Сам по себе InputGestureText
является только косметическим .Если бы мы были слишком разборчивы, мы могли бы утверждать, что механизм создания сочетаний клавиш вообще не имеет каких-либо прямых, неотъемлемых отношений с MenuItem
!
Нам нужно вместо этого (или дополнительно) зарегистрировать слушателядля Ctrl-G на уровне Window
, чтобы поймать нажатие клавиши.Итак, на верхнем уровне ваших тегов Window вставьте это (по сути отсюда ):
<Window.InputBindings>
<KeyBinding Modifiers="Control"
Key="G"
Command="{StaticResource hwc}"
CommandParameter="window input binding"
/>
</Window.InputBindings>
Обратите внимание, что вы можете поместить CommandParameter
теги в KeyBinding
, перемещаяэто от самозакрывающегося фрагмента XML до «реального» открытия и закрытия тегов KeyBinding
.
И все готово.Запустите ваше приложение и нажмите Ctrl-G.Whaddup.
Довольно просто, как только вы получаете игроков прямо, и гораздо меньше волшебной привязки, чем у большинства вводных команд и MenuItems
, я думаю.
Возможный профессиональный совет:
Вся эта вещь 1108 * некоторое время смущала меня.Я считаю, что это просто для определенных типов команд.То есть вы не можете просто подключить любой Command
, какой захотите.Такие вещи, как что здесь хвастается (в том, что, по общему признанию, достойное вступительное руководство!) ...
Это может быть не совсем очевидно, но с помощью команд мы просто получиливсе бесплатно: сочетания клавиш, текст и InputGestureText на элементах, а WPF автоматически включает / отключает элементы в зависимости от активного элемента управления и его состояния.В этом случае обрезка и копирование отключены, потому что текст не выделен, но вставка включена, потому что мой буфер обмена не пуст!
... немного волшебно и не обязательно хорошо, и может сбивать с толку, когда вы новичок в меню WPF.