WPF - How to prevent keyboard focus transfer to a user control that is clicked by the mouse

94 Views Asked by At

I have a MyToggleButton user control that inherits from System.Windows.Controls.Primitives.ToggleButton.

If keyboard focus is on another control, and I left-mouse click the MyToggleButton, the keyboard focus is transferred to the MyToggleButton control.

Is there a way that I can prevent the keyboard focus transfer if the MyToggleButton is left-mouse clicked?

NOTE: the user must still be able to Tab to the MyToggleButton control, which would set the keyboard focus to it. I just don't want the user to be able to set keyboard focus to it via a left-mouse click.

Again, the control needs to be clickable via a left-mouse click. I DO NOT want the control to have keyboard focus after it is clicked.

2

There are 2 best solutions below

3
On

You can make your control insensitive to mouse input by setting HitTestVisible to false or by consuming the PreviewMouseLeftButtonDown event and marking it as handled. Both ways have the side effect that mouse interaction is partially or fully inhibited for the control. Using the event handler you still can do right-clicks. Keyboard nav and input however is not effected and still functional.
Here is an example how it works with Textboxes. You can step through all 4 textboxes with TAB, but you can not select the 2nd and 3rd with the left mouse, the 3rd however is responsive to right-mousebutton-clicks. The focused textbox always appears in lightly red background for demo purpose.

<Window x:Class="WpfAppDummy1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="450" Width="800">
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
                <Setter Property="Background" Value="#FEFE"/>
                <Style.Triggers>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="Background" Value="#FF88" />
                        <Setter Property="Foreground" Value="#FFF8" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Resources>
        <TextBox>Hi</TextBox>
        <TextBox IsHitTestVisible="False">Hello</TextBox>
        <TextBox PreviewMouseLeftButtonDown="OnPreviewMouseLeftButtonDown">Howdy</TextBox>
        <TextBox>Hey Ho</TextBox>
    </StackPanel>

And that's the eventhandler (stub):

// C# code behind 
 private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; }
1
On

Set the ToggleButton's Focusable property to false.

Focusable="False"