WPF MVVM KeyBinding not being recognized right away and not always working
Asked Answered
F

3

6

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?

Function answered 22/4, 2010 at 14:6 Comment(0)
C
6

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.

Compete answered 22/4, 2010 at 15:7 Comment(4)
I'm going to try using CommandReference to bind the inputs as you suggest. I currently have visual studio 2010 so I haven't tried mole. (Do you perhaps know of another way to check this?) But I am a bit confused about some information presented in the article. According to the article I should be getting an exception but as of right now but my application is running fine short of the issues I am currently dealing with at the moment.Function
Your answer did help as far as button click behavior but, I just had to use FocusManager.FocusedElement="{Binding ElementName=input}" to set the focus of the textbox. But the Command Reference made no change to the app although I'm definitely going to keep it in mind for Attaching non-dependency properties when I'm in a bind in the future. No stupid binding pun intended. lolFunction
An example of the ClickMode: I mentioned eariler <Button Content="1" Height="23" HorizontalAlignment="Right" Margin="0,106,294,176" Width="23" Command="{Binding Path=IAppendToUserInput}" CommandParameter="1" ClickMode="Press" />Function
Good to know the command reference didn't make a difference, but glad this helped regardless. I hadn't run across this particular scenario before, so I'll make sure to jot this down so I also have it in the future.Compete
S
1

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).

Salivation answered 21/3, 2011 at 17:52 Comment(0)
T
1

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();
    }
Tchao answered 12/2, 2020 at 16:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.