web-dev-qa-db-fra.com

Liaison d'une clé de raccourci WPF à une commande dans le ViewModel

J'ai une application WPF qui utilise le modèle MVVM. Accrocher des boutons au VM est assez simple car ils implémentent l'ICommand. J'ai un menu contextuel qui fonctionne de manière similaire. L'étape suivante consiste à créer des touches de raccourci pour le menu contextuel. Je peux ' t comprendre comment obtenir la touche de raccourci pour appeler la commande. Voici un exemple:

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

maintenant j'ai ajouté ceci:

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

pour essayer de connecter les touches de raccourci à la même liaison, mais cela ne fonctionne pas. L'erreur est:

Erreur 169 Une "liaison" ne peut pas être définie sur la propriété "Command" de type "KeyBinding". Une "liaison" ne peut être définie que sur une propriété de dépendance d'un objet de dépendance.

N'y a-t-il pas un moyen de connecter cet événement à la commande? Je ne peux pas comprendre cela.

merci d'avance!

Facture

37
Bill Campbell

J'ai écrit une extension de balisage personnalisée pour "lier" InputBindings aux commandes, qui peuvent être utilisées presque comme une vraie liaison:

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

Notez que cette extension de balisage utilise une réflexion privée, elle ne peut donc être utilisée que si votre application s'exécute en toute confiance ...

Une autre option consiste à utiliser la classe CommandReference. Il peut être trouvé dans la boîte à outils MVVM disponible ici . C'est probablement une approche plus propre, mais un peu plus complexe à utiliser.

Notez que dans WPF 4, le InputBinding.Command, InputBinding.CommandParameter et InputBinding.CommandTarget les propriétés sont des propriétés de dépendance, elles peuvent donc être liées normalement

27
Thomas Levesque

Le code suivant peut être utilisé pour lier une touche de raccourci directement à une commande:

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

Ajoutez ceci après Window.Resources dans le code XAML de votre vue.

39
Michel Keijzers

Je suis d'accord que le faire en XAML est idéal, mais pour des raisons d'exhaustivité, vous pouvez également ajouter votre liaison dans le code. Si vous le faites dans le constructeur, assurez-vous juste que c'est après l'appel à InitializeComponent()

InputBindings.Add(new KeyBinding(btnUpdate, new KeyGesture(Key.U, ModifierKeys.Control));
8
Eddie Deyo

Ont pu ajouter des raccourcis clavier au niveau DataGrid. Comme ça :

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>

Voir le modèle:

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 ;
}
0
Tesfay K. Aregay