Commandbar not getting focus -- gotta use keyboard

147 Views Asked by At

My little project is progressing well, however I'm stumbling over something which is probably stupid...

Somehow, when I open the application, nothing gets focus, I have to use the "tab" key to be able to move the focus to the commandbar and to be able to use the keyboard shortcuts.

And then....

WHen I use the Scrollviewer to move the image or zoom, I cannot use the keyboard shortcuts again, until I use the "tab" to move it to the commandbar.

I've tried

cmdbar.Focus(FocusState.Programmatic);

a bit everywhere in the app where I think that it may be useful, to no avail. I've also tried to use the Keyboard Accelerators, but it does not help. Any tips?

Here is my XAML code:

<Page.Resources>
    <DataTemplate x:Key="myResourceTemplate">
        <TextBlock Text="{Binding}" MaxHeight="10" FontSize="8" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" LineHeight="9" Height="Auto" />

    </DataTemplate>
</Page.Resources>

<Page.BottomAppBar>
    <CommandBar x:Name="cmdbar"  ClosedDisplayMode="Compact" HorizontalAlignment="Left" HorizontalContentAlignment="Left" VerticalAlignment="Center" KeyUp="kb_openkey" Opacity="1" Visibility="Visible" Background="#260000FF">
        <CommandBar.Content>
            <Grid/>
        </CommandBar.Content>
        <AppBarButton Icon="ZoomIn" Label="AppBarButton" Tapped="Zoomin_Click"/>
        <AppBarButton Icon="ZoomOut" Label="AppBarButton" Tapped="Zoomout_Click"/>

        <AppBarToggleButton x:Name="randomstatus" Icon="Shuffle" Label="Random" Tapped="Togglerandom"/>

        <... a bunch of other buttons >

    </CommandBar>
</Page.BottomAppBar>

<Grid x:Name="imggrid" Background="Black" BorderBrush="Black" KeyUp="kb_openkey">
    <ScrollViewer x:Name="imageView_scroller" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled" ZoomMode="Enabled" RequestedTheme="Dark" KeyUp="kb_openkey">
        <Image x:Name = "ctlImage" Grid.Column ="0" VerticalAlignment = "Stretch"  HorizontalAlignment = "Stretch"  Stretch = "Uniform"
            PointerWheelChanged="ctlImage_PointerWheelChanged"
            ManipulationMode = "TranslateX, TranslateY, Scale" 
            ManipulationStarted = "ctlImage_ManipulationStarted" 
            ManipulationDelta = "ctlImage_ManipulationDelta"
            ManipulationCompleted = "ctlImage_ManipulationCompleted"   

            KeyUp="kb_openkey"
           >
            <Image.RenderTransform>
                <CompositeTransform x:Name="image_Transform" ></CompositeTransform >
            </Image.RenderTransform >
        </Image>
    </ScrollViewer>

</Grid>

And here is how I handle keyboard input:

    void kb_openkey(object sender, KeyRoutedEventArgs e)
    {
        if ((int)e.Key >= 1 && (int)e.Key <= 255)
        {
            switch ((int)e.Key)
            {
                case 70: //A
                    ....dothis....;
                    break;
                case 65: //A
                    .... dothat....;
                    break;
             }
        }
    }
2

There are 2 best solutions below

0
On BEST ANSWER

@touseefbsb, very useful!!! Thanks! This handles the key no matter what has got focus and is being clicked on.

So my code is, for reference:

In XAML, in the page section, add:

Loaded="initkbd"
Unloaded="unloadkbd"

And in the C# portion, add:

    //Add the key handler method to the KeyDown handlers
    private void initkbd(object sender, RoutedEventArgs e)
    {
        Window.Current.CoreWindow.KeyDown += kb_openkey;
        cmdbar.Content = "Added to keys";
    }

    //Remove the keyhandler method from the list
    private void unloadkbd(object sender, RoutedEventArgs e)
    {
        Window.Current.CoreWindow.KeyDown -=kb_openkey;
    }

and then, the key handler looks like this:

    private void kb_openkey(CoreWindow sender, KeyEventArgs e)
    {
        //Mark the event as handled
        e.Handled = true;


        int keypressed = (int) e.VirtualKey;

        //Than handle the key, based on its keycode
        if ((int)keypressed >= 1 && (int)keypressed <= 255)
        {                
            switch (keypressed)
            {
                case 70: //F
                    //do something when F is presed
                    break;

                case 76:  //L dialog to show items
                    //Do something when L is pressed
                    break;

            }
        }

     }
3
On

you do not need to set focus in order to use KeyboardAccelrators as shortcuts. Hence you do not need the keyup or keydown events on your image or command bar, unless they have some other task irrelevant of setting focus.

you should use KeyBoardAccelrators in your command bar with AccessKey and any options modifiers like Ctrl or Shift

an example of AccessKey on AppBarButton

<AppBarButton 
    Icon="Copy" 
    Label="Copy" 
    ToolTipService.ToolTip="Copy (Ctrl+C)" 
    Click="OnCopy" 
    AccessKey="C">
    <AppBarButton.KeyboardAccelerators>
      <KeyboardAccelerator 
        Modifiers="Control" 
        Key="C" />
    </AppBarButton.KeyboardAccelerators>
</AppBarButton>

you can find more details in the link of docs I provided above.

Update :

when you tap on another UI element the focus from previous element is removed automatically, you do not need a KeyUp event on your image as well as commandbar, you just just use a global CoreWindow.KeyDown which can help you in any key related commands you want to accomplish