简体   繁体   中英

Modify button style when receiving focus via <tab> but not when clicked on

What I want to do

When tabbing through the user interface most WPF controls display a dashed border when they receive keyboard focus. They do not display this border when they are clicked on with the mouse.

I have a button with a custom control template and I want the same behavior as above however I don't just want to add a border but I want to modify the appearance of the button itself.

What I tried

  • Customizing the FocusVisualStyle . This doesn't give me enough flexibility because the template set by the FocusVisualStyle is added on-top of the button. As far as I am aware this can not be used to modify (style, animate,...) the button itself in any way.

  • Styling the button using Triggers with the IsFocused and/or IsKeyboardFocused properties as well as EventTriggers with the Got/LostFocus and/or Got/LostKeyboardFocus events. That doesn't work either because all of those seem to get triggered when I click on the button too.

Example code

<StackPanel VerticalAlignment="Center" Width="150">

    <StackPanel.Resources>

        <ControlTemplate x:Key="CustomButtonTemplate" TargetType="Button">
            <!--A simple black border with a content presenter-->
            <Border BorderBrush="Black" BorderThickness="1" CornerRadius="2">
                <ContentPresenter x:Name="Presenter" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" />
            </Border>
            <ControlTemplate.Triggers>
                <!--When receiving keyboard focus modify the button text-->
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter TargetName="Presenter" Property="Content" Value="I have keyboard focus" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

        <Style x:Key="CustomFocusVisualStyle" TargetType="Control">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <!--Display a red border-->
                        <Border BorderThickness="1" CornerRadius="2" BorderBrush="Red" Margin="-1" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </StackPanel.Resources>

    <Button Content="I am a normal button" Margin="5" />

    <Button Content="I am a custom button" Margin="5"
            Template="{StaticResource CustomButtonTemplate}"
            FocusVisualStyle="{StaticResource CustomFocusVisualStyle}" />

</StackPanel>

Note how the custom red focus border shows up only when you tab between the two buttons but not when you click the buttons. The custom button text however gets modified in either case.

How can I achieve this?

Ok, after countless hours, I finally found a solution that works for my scenario. I hope it works for yours as well.

Forget FocusVisualStyle , it is junk. I'm using a MultiTrigger that is tied to IsKeyboardFocused=True and IsMouseCaptured=False .

Here is what my style looks like now:

<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Style.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsKeyboardFocused" Value="True"/>
            <Condition Property="IsMouseCaptured" Value="False"/>
        </MultiTrigger.Conditions>
        <Setter Property="BorderBrush" Value="Green" />
        <Setter Property="BorderThickness" Value="2" />
    </MultiTrigger>
</Style.Triggers>

This gives me a green ring around my button only when tabbed to, not when focused via mouse.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM