Search code examples
c#wpfxamlcontroltemplate

How to make a custom focused effect be visible only if the keyboard navigation mode is on in WPF?


I have to use a custom template for a WPF control (a RadioButton) and the control has to have a custom implementation of the Focused effect. Because of that don't use the FocusVisualStyle property but implement the effect inside the control template and I want to use the ControlTemplate's Triggers to enable or disable the effect like that:

<ControlTemplate.Triggers>
    <Trigger Property="IsKeyboardFocused" Value="True">
        <Setter TargetName="FocusEffect" Property="Visibility" Value="Visible" />
    </Trigger>
</ControlTemplate.Triggers>

But the problem is that the default Windows behaviour is that the focus effect is visible only when the keyboard navigation mode is on (the user used the Tab key or pressed the Alt key). If I use only the IsKeyboardFocused property, I have the effect even if the control has been clicked with the mouse which should not be the case.

Which property (properties) do I need to use as a trigger to achieve the default behaviour?


Solution

  • In fact, you can freely design a Style for FocusVisualStyle. It merely defines a control to be overlayed.

    A Style to surround the RadioButton's mark would be like the following.

    <Style x:Key="OptionMarkFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"
                               HorizontalAlignment="Left"
                               Stroke="Black"
                               StrokeThickness="1"
                               StrokeDashArray="1 2"
                               SnapsToDevicePixels="True"/>               
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <StackPanel>
        <RadioButton FocusVisualStyle="{StaticResource OptionMarkFocusVisual}" Content="AAA"/>
        <RadioButton FocusVisualStyle="{StaticResource OptionMarkFocusVisual}" Content="BBB"/>
        <RadioButton FocusVisualStyle="{StaticResource OptionMarkFocusVisual}" Content="CCC"/>
    </StackPanel>
    

    You can create alternative Styles as you wish.

    Octagon:

    <Style x:Key="OptionMarkFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid HorizontalAlignment="Left"
                          SnapsToDevicePixels="True">
                        <Polygon Points="1,0 3,0 4,1 4,3 3,4 1,4 0,3 0,1"
                                 Stretch="Uniform"
                                 Stroke="Black"
                                 StrokeThickness="1"
                                 StrokeDashArray="1 2"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    Crosshair:

    <Style x:Key="OptionMarkFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>                
                    <Grid HorizontalAlignment="Left"
                          SnapsToDevicePixels="True"
                          UseLayoutRounding="True">
                        <Path Data="M 1,0 L 1,2 M 0,1 L 2,1"
                              Stretch="Uniform"
                              Stroke="Gray"
                              StrokeThickness="1"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>