Search code examples
c#uwpfocuscommandbar

Commandbar not getting focus -- gotta use keyboard


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;
             }
        }
    }

Solution

  • @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;
    
                }
            }
    
         }