Сочетания клавиш MenuItem в «чистом» MVVM?

Все меню / контекстные меню / панели инструментов, которые я использую в wpf, объявлены в коде ViewModel примерно так:

MenuService.Add( new MenuItem()
  {
    Header = "DoStuff",
    Command = new relayCommand( DoStuff, () => CanDoStuffExecute() )
    // some more properties like parent item/image/...
  } );

MenuService предоставляет единую точку привязки, которая представляет собой иерархический список MenuItem и привязывается к фактическому ItemsSource меню в xaml.

Это работает очень хорошо, и теперь я хотел бы добавить сочетания клавиш таким же удобным способом. В идеале MenuItem получит свойство типа System.Windows.Input.KeyGesture , поэтому я могу просто написать

Shortcut = new KeyGesture( Key.D, ModifierKeys.Control )

, что приведет к тому, что команда вызываемого элемента будет вызвана при нажатии Ctrl + D в окне, которому принадлежит меню, что также приведет к автоматическому отображению в меню «Ctrl + D».

Однако здесь я заблудился: я хотел установить коллекцию MenuItem.InputBindings через привязку данных, но она предназначена только для получения. Как я могу в любом случае положить туда предметы? Или есть фреймворк MVVM, который уже поддерживает что-то подобное? Большинство вопросов и ответов, которые я обнаружил по сочетаниям клавиш, связаны с их настройкой через xaml, что бесполезно.

Обновление

Поиск «relaycommand vs routeduicommand» и «relaycommand keygesture» и т. Д. Дал достаточно информации, чтобы придумать работающее, хотя и хакерское решение. Определенно есть другие и лучшие способы, но на данный момент для меня это очень низкий приоритет, и он отлично справляется со своей задачей.Я добавил два свойства к классу MenuItem следующим образом:

//Upon setting a Gesture, the original command is replaced with a RoutedCommand
//since that automatically gives us proper display of the keyboard shortcut.
//The RoutedCommand simply calls back into the original Command.
//It also sets the CommandBinding property, which still has to be added to the
//CommandBindingCollection of either the bound control or one of it ancestors
public InputGesture Gesture
{
  set
  {
    var origCmd = Command;
    if( origCmd == null )
      return;
    var routedCmd = new RoutedCommand( Header,
      typeof( System.Windows.Controls.MenuItem ),
      new InputGestureCollection { value } );
    CommandBinding = new CommandBinding( routedCmd,
      ( sender, args ) => origCmd.Execute( args.Parameter ),
      ( sender, args ) => { args.CanExecute = origCmd.CanExecute( args.Parameter ); } );
    Command = routedCmd;
  }
}

//CommandBinding created when setting Gesture
public CommandBinding CommandBinding { get; private set; }

Таким образом, это дает функциональность, о которой я просил изначально (т.е. добавление сочетаний клавиш в код, где они легко настраиваются и т. Д.). Осталось только зарегистрировать привязки команд. На данный момент это делается простым добавлением их всех в Application.Current.MainWindow.CommandBindings.

5
задан stijn 17 April 2014 в 13:53
поделиться