Aaj
Aaj

Reputation: 259

KeyboardNavigation.ControlTabNavigation Application Wide?

I have an issue I've been trying to deal with - the following:

KeyboardNavigation.ControlTabNavigation="None"

doesn't seem to work anyplace in my application despite my best efforts...I'm not entirely sure why but regardless of what I do, the CTRL+TAB functionality always works, and in my case the behavior is detrimental to how I'd like my tab controls to operate. Ideally, rather than placing the above tag in every container in my application (which I can't get to work anyway), I'd like to disable ControlTabNavigation across the entire application. Is there a way to do this without having to go container by container, and is there any obvious "gotchas" that normally keep the above from working properly?

Thank you! Aj

Upvotes: 1

Views: 2208

Answers (2)

Aaj
Aaj

Reputation: 259

I hadn't looked at this issue in a while, but since Bill asked it sparked a renewed interest. Rather than going control by control, I used an empty command as Bill suggested, but applied it to a TabControl template...as Bill pointed out, somewhat of a counter-intuitive solution, but it works (I also accounted for Ctrl+Shift+Tab which is just the opposite direction of Ctrl+Tab):

MyClass:

public static readonly RoutedCommand CancelTabChangeCommand = new RoutedCommand() { };

XAML:

<Style TargetType="{x:Type TabControl}">    
  <Setter Property="Template">
     <Setter.Value>
        <ControlTemplate TargetType="{x:Type TabControl}">
           <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                    <Grid.InputBindings>
                        <KeyBinding Command="{x:Static local:myClass.CancelTabChangeCommand}" Key="Tab" Modifiers="Control" />
                        <KeyBinding Command="{x:Static star:Startup.CancelTabChangeCommand}" Key="Tab" Modifiers="Shift+Control"/>
                    </Grid.InputBindings>

I left off the rest of my class and XAML as it wasn't pertinent to the example, but I'm happy to provide more if anyone needs it. On a related note, I also found that create a control template for the TabItem and setting the IsTabStop property to false also keeps my users from tabbing across and changing tabs in that fashion as well...in case anyone was having this issue as I was.

Hope it helps!

Upvotes: 0

Bill
Bill

Reputation: 1417

I find that the KeyboardNavigation does not work as I would expect as it pertains to Ctrl-Tab and a TabControl. I put together a simple prototype and KeyboardNavigation.ControlTabNavigation="None" just does not seem to have the expected impact on the switching of Tabs using Ctrl-Tab, once I left-click a tab and the keyboard focus is within the TabControl.

However, using InputBindings with a Command can override the unwanted Ctrl-Tab default behavior. From there, I found that KeyboardNavigation.TabNavigation="Cycle", as well as the other the other options for TabNavigation seem to behave reasonably. Using The FocusManager and other techniques described in the resource links below should allow one to obtain desired keyboard navigation, albeit using somewhat counter-intuitive techniques.

The InputBindings do have to be set for each control that has the unwanted default behavior, although a more sophisticated solution might walk the visual tree to set the InputBindings for all controls of a certain type, for example. I found having the Command simply do nothing neutralizes the key sequence adequately. In my example, I display a dialog box for testing.

Note, below Command binding requires you target WPF 4.0; please see resources at end of post for resource on how to target WPF 3.5 or earlier

In XAML:

<TabControl 
    x:Name="tabControl1"
    IsSynchronizedWithCurrentItem="True"
    SelectedItem="{Binding SelectedTabItem}"
    ItemsSource="{Binding TabItemViewModels}"
    KeyboardNavigation.ControlTabNavigation="None"
    KeyboardNavigation.TabNavigation="Continue">

            <TabControl.InputBindings>
                <KeyBinding Modifiers="Control"
                    Key="Tab"
                    Command="{Binding ShowDialogCommand}" />
            </TabControl.InputBindings>
</TabControl>

Note, in above XAML, KeyboardNavigation.ControlTabNavigation="None" is of no effect and can be eliminated.

In backing DataContext, typically a ViewModel:

Declare your binding property:

public RelayCommand ShowDialogCommand
{
     get;
     private set;
}

Initialize the property; for example, can be in the constructor of the ViewModel (Note, RelayCommand is from MVVM-Light library.):

ShowDialogCommand = new RelayCommand(() =>
            {
                MessageBox.Show("Show dialog box command executed", "Show Dialog Box Command", MessageBoxButton.OK, MessageBoxImage.Information); 
            });

Resources:

Helpful StackOverflow post on KeyBindings

More detail on KeyBinding to a Command; describes special CommandReference technique needed if targeting WPF framewrok 3.5 or earlier

Microsoft's Focus Overview

Upvotes: 1

Related Questions