Tutti i menu/contextmenus/barre degli strumenti che uso in WPF vengono dichiarati nel codice ViewModel più o meno in questo modo:MenuItem scorciatoie da tastiera in MVVM 'puro'?
MenuService.Add(new MenuItem()
{
Header = "DoStuff",
Command = new relayCommand(DoStuff,() => CanDoStuffExecute())
// some more properties like parent item/image/...
});
Il MenuService fornisce un unico punto di legame che è un elenco gerarchico di MenuItem e viene legato alla effettiva menu del ItemsSource in xaml.
Questo funziona molto bene e ora mi piacerebbe aggiungere scorciatoie da tastiera nello stesso modo conveniente. Idealmente MenuItem otterrebbe una proprietà di tipo System.Windows.Input.KeyGesture
così posso scrivere semplicemente
Shortcut = new KeyGesture(Key.D, ModifierKeys.Control)
che comporterebbe il Comando della voce di essere chiamati premendo Ctrl + D nella finestra che possiede il menu, e che avrebbe anche portare a visualizzare automaticamente "Ctrl + D" nel menu.
Tuttavia, mi sono perso qui: volevo impostare la raccolta MenuItem.InputBindings tramite il collegamento dati, ma è di sola lettura. Come posso ottenere comunque degli oggetti? O c'è un framework MVVM che supporta già qualcosa di simile? La maggior parte di q & a che ho trovato sulle scorciatoie da tastiera riguardano l'impostazione delle scorciatoie tramite xaml, il che non aiuta.
Aggiornamento
Cerca per 'relaycommand vs routeduicommand e 'relaycommand keygesture' etc ha rivelato informazioni sufficienti per trovare una soluzione di lavoro se hacky. Ci sono sicuramente altri e migliori modi là fuori, ma al momento questa è una priorità ultra bassa per me e fa il lavoro perfettamente. Ho aggiunto due proprietà alla classe MenuItem come questo:
//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; }
Quindi questo dà la funzionalità che ho chiesto in origine (cioè l'aggiunta di scorciatoie da tastiera nel codice dove sono facilmente configurabili, ecc). Non resta che registrare i commandbindings. Al momento questo viene fatto semplicemente aggiungendoli tutti a Application.Current.MainWindow.CommandBindings.
Potete fornire un esempio di codice? Vuoi dire che dovrei definire il menu completo in xaml? O solo la scorciatoia? Mi piacerebbe vedere come ... Ho bisogno di cose come un menu 'Strumenti' globale in cui i plug-in possono aggiungere sottomenu a volontà - può anche essere fatto in xaml? Supponiamo anche che possa in qualche modo sporcare il codice con xaml, no? Ora tutto ciò di cui ho bisogno per aggiungere un comando di menu è il codice come mostrato. Questo è il più breve e maneggevole che può ottenere e funziona meravigliosamente. A proposito, il tuo muro di mattoni funziona in due direzioni: devo ancora vedere un'app su larga scala in cui nessun pezzo UX singolo è definito nel codice. Questo è un mito. – stijn
Hai assolutamente ragione - e ho visto alcuni progetti UX WPF piuttosto grandi che hanno cercato davvero di evitare qualsiasi codice - e sono finiti inutilmente ottusi. Cerco di usare solo l'approccio che funziona ed è più semplice. Ecco un frammento del campione (pardon la mancanza di finese - io sono sicuro come formattare questo su questo sito) .. '
la tua risposta, incolla il codice, selezionalo e fai clic sul pulsante * Esempio di codice *. – stijn