2010-03-04 8 views
33

Tengo una aplicación WPF que usa el patrón MVVM. Conectar los botones a la VM es bastante directo ya que implementan ICommand. Tengo un menú contextual que funciona de manera similar. El siguiente paso es crear teclas de método abreviado para el menú contextual. No puedo entender cómo hacer que la tecla de acceso directo invoque el comando. Aquí está un ejemplo:Enlazar una clave abreviada de WPF a un comando en el modelo de vista

<MenuItem Header="Update" Command="{Binding btnUpdate}" > 
    <MenuItem.Icon> 
     <Image Source="/Images/Update.png" 
       Width="16" 
       Height="16" /> 
     </MenuItem.Icon> 
    </MenuItem> 

ahora hemos añadido esto:

<Window.InputBindings> 
    <KeyBinding Key="U" 
       Modifiers="Control" 
       Command="{Binding btnUpdate}" /> 
</Window.InputBindings> 

tratar de conectarse las teclas de acceso directo a la misma ligadura, pero esto no funciona. El error es:

Error 169 Un 'Enlace' no se puede establecer en la propiedad 'Comando' del tipo 'Enlace de clave'. Un 'Enlace' solo se puede establecer en una DependencyProperty de un DependencyObject.

¿No hay una forma de conectar este evento al Comando? No puedo resolver esto.

gracias de antemano!

Bill

+0

Debo mencionar que estoy usando RelayCommand de Josh Smith también. –

Respuesta

25

me escribió una custom markup extension de "atar" InputBindings a los comandos, que puede ser utilizado casi como una verdadera unión:

<UserControl.InputBindings> 
    <KeyBinding Modifiers="Control" 
       Key="E" 
       Command="{input:CommandBinding EditCommand}"/> 
</UserControl.InputBindings> 

Tenga en cuenta que esta extensión de marcado utiliza la reflexión privada, por lo que puede solo se usará si su aplicación se ejecuta con plena confianza ...

Otra opción es utilizar la clase CommandReference. Se puede encontrar en el kit de herramientas MVVM disponible here. Probablemente sea un enfoque más limpio, pero un poco más complejo de usar.

Nótese que en WPF 4, los InputBinding.Command, InputBinding.CommandParameter y InputBinding.CommandTarget propiedades son propiedades de dependencia, por lo que se pueden unir normalmente

+0

¡Excelente! Esto es justo lo que estaba buscando. ¡¡Gracias!! –

+0

Seguí a los ex en los documentos WPF MVVM, ¡excelentes ejemplos! Exactamente lo que quiero hacer Desafortunadamente, los elementos del menú contextual funcionan bien, pero las teclas de método abreviado no hacen nada. Ni siquiera puedo descifrar para depurar esto ya que no pasa nada cuando presiono las teclas de acceso directo. –

+0

¿Podría ser que estoy tratando de usar estos en teclas de método abreviado en un ContextMenu en lugar de un menú estándar? –

0

se muestra un enfoque alternativo para la unión de una clave de WPF de acceso directo a una propiedad de comandos de la ViewModel en la muestra de ShortcutKey del proyecto WPF Application Framework (WAF).

+0

Gracias ... Necesitaré un poco de tiempo para analizarlo (lo que significa que no tengo mucho tiempo ahora, pero voté a favor porque el enlace me parece muy útil (no solo por mi pregunta solamente). –

8

Estoy de acuerdo en que hacerlo en XAML es ideal, pero para mayor completud, también podría agregar su encuadernación en el código. Si lo haces en el constructor, sólo asegúrese de que es después de la llamada a InitializeComponent()

InputBindings.Add(new KeyBinding(btnUpdate, new KeyGesture(Key.U, ModifierKeys.Control)); 
+0

+1 Este método me permitió para ponerlo en mi vista porque necesitaba la función solo para trabajar con elementos de la interfaz de usuario. – CaptainBli

+2

Pero esto vincula un botón de control, 'btnUpdate' a la tecla de acceso directo Ctrl-U, no a un comando como el de XAML de Michel Keijzers. – ProfK

+1

I estaba respondiendo la publicación original que intentaba vincularse a algo llamado "btnUpdate". –

30

El siguiente código se puede utilizar para vincular una clave de acceso directo directamente a un comando:

<Window.InputBindings> 
    <KeyBinding Command="{Binding Path=NameOfYourCommand}" 
       Key="O" 
       Modifiers="Control"/> 
</Window.InputBindings> 

Añadir esta después de Window.Resources en el código XAML de su vista.

+15

Esta solución funciona en .NET 4 y posteriores. –

+3

Sí no estoy seguro de cuál es el problema de OP fue, pero esto funciona bien. (Estoy usando luz MVVM) – GONeale

+6

Dijo específicamente que esto no funcionó, y la respuesta seleccionada explica por qué: H e no está usando WPF4. No estoy seguro de por qué publica su código exacto como una "respuesta" – aaronburro

0

Se ha podido agregar Keybinding en el nivel DataGrid.De esta manera:

Xaml:

<DataGrid 
        AutoGenerateColumns="False" 
        ItemsSource="{Binding YourCollection}"       
        CanUserAddRows="False"       
        HeadersVisibility="Column" 
        CanUserDeleteRows="False" 
        CanUserSortColumns="True" 
        CanUserResizeRows="False" 
        CanUserResizeColumns="False"      
        SelectedItem="{Binding YourSelectedItem}" 
        SelectionMode="Single" 
        SelectionUnit="FullRow" 
        > 
       <DataGrid.ContextMenu> 
        <ContextMenu> 
         **<MenuItem Header="Delete" InputGestureText="Del" Command="{Binding DeleteCommand}">** 
         </MenuItem> 
        </ContextMenu> 
       </DataGrid.ContextMenu> 
       **<DataGrid.InputBindings> 
        <KeyBinding Key="Delete" Command="{Binding DeleteCommand}" CommandParameter="Delete"/>** 
       </DataGrid.InputBindings> 
       <DataGrid.Columns> 
        <DataGridTextColumn Header="Column Header" Binding="{Binding YourColumn}" IsReadOnly="True" /> 
       </DataGrid.Columns> 
</DataGrid> 

Ver Modelo:

public ICommand DeleteCommand 
      { 
       get 
       { 
        return new DelegateCommand(ExecuteCommand, CanExecute); 
       } 
      } 

    private void ExecuteCommand() 
{ 
// your code to delete here. 
    YourCollection.Remove(YourSelectedItem); 
} 

private void CanExecute() 
{ 
// logic to check if the delete command can execute. 
    return YourSelectedItem != null ; 
} 
Cuestiones relacionadas