Ах, ха! На вопрос я могу ответить! Во-первых, я должен отметить, что лично мне было проще определять и подключать команды в коде, а не в XAML. Это позволяет мне подключать обработчики команд немного гибче, чем это делает весь подход XAML.
Вы должны решить, какие команды вы хотите иметь и с чем они связаны. В моем приложении у меня в настоящее время есть класс для определения важных команд приложения, таких как:
public static class CommandBank
{
/// Command definition for Closing a window
public static RoutedUICommand CloseWindow { get; private set; }
/// Static private constructor, sets up all application wide commands.
static CommandBank()
{
CloseWindow = new RoutedUICommand();
CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
// ...
}
Теперь, поскольку я хотел сохранить весь код вместе, использование подхода только к коду для команд позволяет мне поместить следующие методы в вышеприведенный класс:
/// Closes the window provided as a parameter
public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e)
{
((Window)e.Parameter).Close();
}
/// Allows a Command to execute if the CommandParameter is not a null value
public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
e.Handled = true;
}
Второй способ можно использовать совместно с другими командами без необходимости повторять его повсеместно.
После того, как вы определили команды, подобные этой, вы можете добавить их в любой элемент пользовательского интерфейса. Далее, после того, как окно загружено, я добавляю привязки команд как в Window, так и в MenuItem, а затем добавляю привязку ввода к окну, используя цикл для этого для всех привязок команд. Передаваемый параметр - это само окно, поэтому приведенный выше код знает, какое окно попытаться закрыть.
public partial class SimpleWindow : Window
{
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// ...
this.CommandBindings.Add(
new CommandBinding(
CommandBank.CloseWindow,
CommandBank.CloseWindowExecute,
CommandBank.CanExecuteIfParameterIsNotNull));
foreach (CommandBinding binding in this.CommandBindings)
{
RoutedCommand command = (RoutedCommand)binding.Command;
if (command.InputGestures.Count > 0)
{
foreach (InputGesture gesture in command.InputGestures)
{
var iBind = new InputBinding(command, gesture);
iBind.CommandParameter = this;
this.InputBindings.Add(iBind);
}
}
}
// menuItemExit is defined in XAML
menuItemExit.Command = CommandBank.CloseWindow;
menuItemExit.CommandParameter = this;
// ...
}
// ....
}
У меня также позже есть обработчики событий для событий WindowClosing и WindowClosed, я рекомендую вам сделать фактическую реализацию команд настолько малой и универсальной, насколько это возможно. Как и в этом случае, я не пытался поместить код, который пытается остановить закрытие окна, если есть несохраненные данные, я твердо держал этот код внутри события WindowClosing.
Дайте мне знать, если у вас есть дополнительные вопросы. :)