WPF MVVM KeyBinding not being recognized right away and not always working

14,777

Solution 1

Have you verified that the control actually has focus when it loads by using Mole? It could be that whatever your parent control is keeps focus until your buttons are selected manually. As for the Enter keys, it sounds as if they are probably selecting the last clicked button since it would still have focus instead of firing your commands.

You may need to look at your commands as I'm not sure the declarations are set up correctly. For KeyBindings, your command should be referenced in XAML as a CommandReference, like this article describes.

Solution 2

I'm not sure if this fully answers your question, but most of my keybinding / focus questions are solved by setting Focusable=True on your user control, and then in the code behind, call Focus() on the view's load event.

    <UserControl ....
         Focusable="True"
         Loaded="Act_Loaded" >

    private void Act_Loaded(object sender, RoutedEventArgs e)
    {
        Focus();
    }

Solution 3

I ran into the same issue. I followed up on the focus issue. I found that when I set my focus to a button inside of my form, the commands started working. If my focus item gets deleted and not redirected (such as deleting the last item from a listbox), then none of my commands work.

I manually reset my keyboard focus to a default item in the cases that were leaving my focus ina weird state causing my commands to break. In my case, that was the page loaded event and the delete command (when there were no more items in my list box).

Share:
14,777
Terrance
Author by

Terrance

Updated on June 18, 2022

Comments

  • Terrance
    Terrance about 2 years

    For whatever reason, the KeyBindings for my UserControl aren't working as soon as my WPF Application loads. They do work after I press a button on the form but not when I set focus to the form by clicking or alt tabbing or moving or anything like that. And when they do work my enter keys print a random number. (sometimes 5, sometimes 7 etc...).

    <UserControl x:Class="WpfCalculator.View.CalculatorView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="300"
        >
    <UserControl.InputBindings>
        <KeyBinding Key="DELETE" Command="{Binding Path=IBackspaceOnInput}" />
        <KeyBinding Key="BACKSPACE" Command="{Binding Path=IBackspaceOnInput}" />
    
        <KeyBinding Key="NUMPAD0" Command="{Binding Path=IAppendToUserInput}" CommandParameter="0" />
        <KeyBinding Key="NUMPAD1" Command="{Binding Path=IAppendToUserInput}" CommandParameter="1" />
        <KeyBinding Key="NUMPAD2" Command="{Binding Path=IAppendToUserInput}" CommandParameter="2" />
        <KeyBinding Key="NUMPAD3" Command="{Binding Path=IAppendToUserInput}" CommandParameter="3" />
        <KeyBinding Key="NUMPAD4" Command="{Binding Path=IAppendToUserInput}" CommandParameter="4" />
        <KeyBinding Key="NUMPAD5" Command="{Binding Path=IAppendToUserInput}" CommandParameter="5" />
        <KeyBinding Key="NUMPAD6" Command="{Binding Path=IAppendToUserInput}" CommandParameter="6" />
        <KeyBinding Key="NUMPAD7" Command="{Binding Path=IAppendToUserInput}" CommandParameter="7" />
        <KeyBinding Key="NUMPAD8" Command="{Binding Path=IAppendToUserInput}" CommandParameter="8" />
        <KeyBinding Key="NUMPAD9" Command="{Binding Path=IAppendToUserInput}" CommandParameter="9" />
    
        <KeyBinding Key="D0" Command="{Binding Path=IAppendToUserInput}" CommandParameter="0" />
        <KeyBinding Key="D1" Command="{Binding Path=IAppendToUserInput}" CommandParameter="1" />
        <KeyBinding Key="D2" Command="{Binding Path=IAppendToUserInput}" CommandParameter="2" />
        <KeyBinding Key="D3" Command="{Binding Path=IAppendToUserInput}" CommandParameter="3" />
        <KeyBinding Key="D4" Command="{Binding Path=IAppendToUserInput}" CommandParameter="4" />
        <KeyBinding Key="D5" Command="{Binding Path=IAppendToUserInput}" CommandParameter="5" />
        <KeyBinding Key="D6" Command="{Binding Path=IAppendToUserInput}" CommandParameter="6" />
        <KeyBinding Key="D7" Command="{Binding Path=IAppendToUserInput}" CommandParameter="7" />
        <KeyBinding Key="D8" Command="{Binding Path=IAppendToUserInput}" CommandParameter="8" />
        <KeyBinding Key="D9" Command="{Binding Path=IAppendToUserInput}" CommandParameter="9" />
    
        <KeyBinding Key="ADD" Command="{Binding Path=IAppendToUserInput}" CommandParameter="+" />
        <KeyBinding Key="SUBTRACT" Command="{Binding Path=IAppendToUserInput}" CommandParameter="-" />
        <KeyBinding Key="MULTIPLY" Command="{Binding Path=IAppendToUserInput}" CommandParameter="*" />
        <KeyBinding Key="DIVIDE" Command="{Binding Path=IAppendToUserInput}" CommandParameter="/" />
    
        <KeyBinding Key="Return" Command="{Binding Path=ICalculateExpression}" CommandParameter="" />
        <KeyBinding Key="Enter" Command="{Binding Path=ICalculateExpression}" CommandParameter="" />
        <KeyBinding Key="Escape" Command="{Binding Path=IClearInput}" CommandParameter="" />
    
        <KeyBinding Gesture="CTRL+M" Command="{Binding Path=IRememberExpression}" CommandParameter="" />
        <KeyBinding Gesture="CTRL+R" Command="{Binding Path=IRecallExpression}" CommandParameter="" />
        <KeyBinding Gesture="CTRL+X" Command="{Binding Path=IForgetExpression}" CommandParameter="" />
    
        <KeyBinding Key="Left" Command="{Binding Path=IMMoveCursor}" CommandParameter="1" />
        <KeyBinding Key="Right" Command="{Binding Path=IMMoveCursor}" CommandParameter="-1" />
    
    </UserControl.InputBindings>
    
    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="305" Width="489">
        <TextBox Name="input" HorizontalAlignment="Right"  IsReadOnly="True" Margin="0,12,200,271" Text="{Binding Path=UserInput}" Width="275" />
        <Button Content="CE" Margin="143,0,323,147" Command="{Binding Path=IBackspaceOnInput}" CommandParameter="" Height="23" VerticalAlignment="Bottom" />
        <Button Content="1" Height="23" HorizontalAlignment="Right" Margin="0,106,294,176" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="1" />
        <Button Content="2" Height="23" HorizontalAlignment="Right" Margin="0,106,265,176" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="2" />
        <Button Content="3" Height="23" HorizontalAlignment="Right" Margin="0,106,236,176" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="3" />
        <Button Content="4" Height="23" HorizontalAlignment="Right" Margin="0,77,294,205" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="4" />
        <Button Content="5" Height="23" HorizontalAlignment="Right" Margin="0,77,236,205" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="5" />
        <Button Content="6" Height="23" HorizontalAlignment="Right" Margin="0,77,265,205" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="6" />
        <Button Content="7" Height="23" HorizontalAlignment="Right" Margin="0,48,294,234" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="7" />
        <Button Content="8" Height="23" HorizontalAlignment="Right" Margin="0,48,265,234" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="8" />
        <Button Content="9" Height="23" HorizontalAlignment="Right" Margin="0,48,236,234" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="9" />
        <Button Content="0" Height="23" HorizontalAlignment="Left" Margin="201,135,0,147" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="0" />
    
        <Button Content="+" Height="23" HorizontalAlignment="Right" Margin="0,48,201,234" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="+" />
        <Button Content="-" Height="23" HorizontalAlignment="Right" Margin="0,77,201,205" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="-" />
        <Button Content="*" Height="23" HorizontalAlignment="Right" Margin="0,106,201,176" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="*" />
        <Button Content="/" Height="23" HorizontalAlignment="Right" Margin="0,135,201,147" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="/" />
        <Button Content="." Height="23" HorizontalAlignment="Right" Margin="0,135,236,147" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="9" />
    
        <Button Content="C" HorizontalAlignment="Right" Margin="0,164,323,118" Width="23" Command="{Binding Path=IClearInput}" CommandParameter="" />
        <Button Content="MC" Height="23" HorizontalAlignment="Right" Margin="0,0,323,234" VerticalAlignment="Bottom" Width="23" Command="{Binding Path=IForgetExpression}" CommandParameter=""/>
        <Button Content="M+" Height="23" HorizontalAlignment="Right" Margin="0,0,323,176" VerticalAlignment="Bottom" Width="23" Command="{Binding Path=IRememberExpression}" CommandParameter=""/>
        <Button Content="MR" Height="23" HorizontalAlignment="Right" Margin="0,0,323,205" VerticalAlignment="Bottom" Width="23" Command="{Binding Path=IRecallExpression}" CommandParameter=""/>
    
        <Expander ExpandDirection="Left" Header="History" Height="91" HorizontalAlignment="Right" Margin="0,193,200,0" VerticalAlignment="Top" Width="275">
            <ListView ItemsSource="{Binding Path=History}" >
                <ListView.View>
                    <GridView >
                        <GridViewColumn Header="Start" DisplayMemberBinding="{Binding Started}"/>
                        <GridViewColumn Header="End" DisplayMemberBinding="{Binding Completed}"/>
                        <GridViewColumn Header="Expression" DisplayMemberBinding="{Binding Calculation}"/>
                        <GridViewColumn Header="Solution" DisplayMemberBinding="{Binding Result}"/>
                    </GridView>
                </ListView.View>
            </ListView>
        </Expander>
        <Button Command="{Binding Path=ICalculateExpression}" CommandParameter="" IsEnabled="{Binding Path=IsEqualsBtnEnabled}" Content="=" Height="23" Margin="172,0,236,118" VerticalAlignment="Bottom" />
    
    </Grid></UserControl>
    

    I really haven't come across anyone else with this particular problem so I'm not really sure what to give any more than this. Let me know if there is any other info required?