Вопрос

Я немного программировал на WPF, но никогда не понимал шаблона команд.Кажется, что каждый пример предназначен для встроенных: редактируйте, вырезайте, вставляйте.У кого-нибудь есть пример или рекомендации по использованию пользовательских команд?

Это было полезно?

Решение

Ах-ха!Вопрос, на который я могу ответить!Во-первых, я должен упомянуть, что лично мне было проще определять и подключать команды в коде, а не в 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.

Дайте мне знать, если у вас возникнут дополнительные вопросы.:)

Другие советы

В сентябрьском выпуске журнала MSDN за 2008 год Брайан Нойес опубликовал прекрасную статью о RoutedCommand/RoutedEvents!!!

Вот ссылка:http://msdn.microsoft.com/en-us/magazine/cc785480.aspx

Особенность XAML в том, что он подходит для «простых» программ, но, к сожалению, он не работает, когда вы хотите делать такие вещи, как функции совместного использования.Предположим, у вас есть несколько классов и пользовательских интерфейсов, в каждом из которых есть команды, которые никогда не отключались, вам придется написать метод CanAlwaysExecute для каждого окна или пользовательского элемента управления!Это просто не очень СУХОЙ.

Прочитав несколько блогов и попробовав несколько вещей, я решил сделать XAML исключительно ориентированным на внешний вид, стили, анимацию и триггеры.Все мои подключения обработчиков событий и команд теперь находятся в коде программной части.:)

Кстати, еще одна ошибка — это привязка ввода. Чтобы их можно было перехватить, фокус должен быть на объекте, содержащем привязки ввода.Например, чтобы иметь ярлык, который вы можете использовать в любое время (скажем, F1, чтобы открыть справку), эта привязка ввода должна быть установлена ​​для объекта Window, поскольку он всегда имеет фокус, когда ваше приложение активно.Использование метода кода должно упростить эту задачу, даже если вы начинаете использовать элементы управления UserControl, которые могут захотеть добавить привязки ввода к своему родительскому окну.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top