Пример настраиваемого шаблона команды WPF

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
36
0
8 896
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

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.

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

Ваш CanExecuteIfParameterIsNotNull содержит одно из моих неудобств. Почему бы просто не e.CanExecute = e.Parameter! = Null;

Ray 28.11.2008 03:53

@Ray Я не знал, что могу это сделать! Спасибо за редактирование, Дрю. :)

Nidonocu 08.10.2009 03:55

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

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

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

Я писал о множестве ресурсов по командам WPF вместе с примером в прошлом году на http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx

Вставка сюда:

Образец главы Адама Натана о важных новых концепциях в WPF: команды

Статья MSDN: Шаблон команды в WPF

Кейван Найери: как добавлять команды в настраиваемый элемент управления WPF

Ян Гриффитс: ввод, команды и обработчики Avalon

Википедия: Шаблон команды

Библиотека MSDN: обзор команд

Библиотека MSDN: класс CommandBinding

Библиотека MSDN: разделы с инструкциями по вводу и командам

Библиотека MSDN: класс EditingCommands

Библиотека MSDN: класс MediaCommands

Библиотека MSDN: класс ApplicationCommands

Библиотека MSDN: класс NavigationCommands

Библиотека MSDN: класс ComponentCommands

Также в примерах WPF SDK есть хороший пример редактирования RichTextBox, который я расширил. Вы можете найти его здесь: RichTextEditor.zip

blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/… this link is dead :(
Drahakar 10.05.2011 18:51

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

Ссылка здесь: http://msdn.microsoft.com/en-us/magazine/cc785480.aspx

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