Todos los menús/contextmenus/barras de herramientas que utilizo en WPF se declaran en el código modelo de vista más o menos así:Métodos abreviados de teclado de MenuItem en MVVM 'puro'
MenuService.Add(new MenuItem()
{
Header = "DoStuff",
Command = new relayCommand(DoStuff,() => CanDoStuffExecute())
// some more properties like parent item/image/...
});
El Menuservice proporciona un único punto de unión que es una lista jerárquica de Menultem y se une al Menú real de ItemsSource en xaml.
Esto funciona muy bien y ahora me gustaría añadir atajos de teclado de la misma manera conveniente. Idealmente Menultem obtendría una propiedad de tipo System.Windows.Input.KeyGesture
por lo que simplemente puede escribir
Shortcut = new KeyGesture(Key.D, ModifierKeys.Control)
lo que resultaría en el Comando del elemento que se llama al golpear Ctrl + D en la ventana que posee el menú, y que también llevar a mostrar automáticamente "Ctrl + D" en el menú.
Sin embargo estoy perdido aquí: quería establecer la colección MenuItem.InputBindings a través de enlace de datos, pero es conseguir-solamente. ¿Cómo puedo obtener artículos de todos modos? ¿O hay un marco MVVM que ya sea compatible con algo como esto? La mayoría de los q & que encontré en los atajos de teclado tratan sobre la configuración de accesos directos a través de xaml, lo que no sirve de nada.
actualización
Buscando 'RelayCommand vs routeduicommand y 'RelayCommand keygesture' etc reveló suficiente información para llegar a una solución de trabajo a pesar de hacky. Definitivamente hay otras y mejores formas de hacerlo, pero de momento esto es una prioridad muy baja para mí y hace el trabajo a la perfección. He añadido dos propiedades a la clase MenuItem como esto:
//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; }
Así que esto da la funcionalidad pedí originalmente (es decir, añadir atajos de teclado en el código donde sean fácilmente configurable, etc.). Todo lo que queda es registrar los enlaces de comando. Por el momento, esto se hace simplemente agregando todos ellos a Application.Current.MainWindow.CommandBindings.
¿Puede proporcionarnos algún ejemplo de código? ¿Quiere decir que debería definir el menú completo en xaml? ¿O solo el atajo? Me gustaría ver cómo ... Necesito elementos como un menú global de "Herramientas" en el que los complementos pueden agregar submenús a voluntad, ¿eso se puede hacer incluso en xaml? También supongo que puede, sería un poco basura el código con xaml, ¿no? Ahora todo lo que necesito para agregar un comando de menú es el código como se muestra. Eso es lo más corto y práctico que puede llegar y funciona maravillosamente. Por cierto, tu muro de ladrillos funciona en dos direcciones: todavía tengo que ver una aplicación a gran escala donde no se define ninguna pieza de UX en el código ... Eso es un mito. – stijn
Tiene toda la razón, y he visto algunos proyectos WPF UX bastante grandes que intentaban realmente evitar cualquier código, y terminaron innecesariamente obtusos. Intento simplemente usar el enfoque que sea más simple. Aquí hay un fragmento de la muestra (perdón por la falta de finese - estoy seguro de cómo dar formato a este en este sitio web) .. ' –
JamesWHurst
edición su respuesta, pegue el código, selecciónelo y haga clic en el botón * Muestra de código *. – stijn