WPF doesn't draw focus the button when focused programmatically

Ivan Pizhenko 0 Reputation points
2023-10-12T09:20:39.5533333+00:00

I am writing a WPF GUI application using .NET 6.

I have a following visual structure in my main window, but please note ScrollViewer and DockPanel inside it.

<DockPanel>
<!-- .... some more components here.... -->
            <ScrollViewer x:Name="scvApplications"
                          HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
                <DockPanel x:Name="pnlApplications" HorizontalAlignment="Left">
                </DockPanel>
            </ScrollViewer>
</DockPanel>

I want to focus a button programmatically and have custom focus style, just a simple solid black border. For custom focus style I've added following Style definition into my window XAML:

    <Window.Resources>
        <Style x:Key="AppButtonFocusStyle" TargetType="Control">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle StrokeThickness="2" Stroke="Black" SnapsToDevicePixels="true"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

I am creating each of those buttons programmatically, like this:

        _appButtonFocusStyle = (Style)FindResource("AppButtonFocusStyle");
        // ....
        var appButton = new Button()
        {
            Name = $"btn{_nextAppButtonId++}",
            Content = "some text on the button",
            Background = Brushes.Transparent,
            BorderBrush = Brushes.Transparent,
            FocusVisualStyle = _appButtonFocusStyle,
            Tag = "something"
        };
        appButton.Click += ApplicationButton_Click;
        pnlApplications.Children.Add(appButton);

Then, at some point, I'm doing

    Activate();
    firstButton.Focus();

in the code, where firstButton is a first button created. But with this, neither default, nor my custom focus border is drawn. However, when I press right arrow key, focus does move to a next button, my custom focus rectangle is correctly drawn on it. Then, when I press left arrow key, and focus moves back to the button that I've initially focused programmatically, and the custom focus rectangle is correctly removed from focused "next" button and correctly drawn on the "first" button.

From this, I make conclusion that when I've done the firstButton.Focus(), "firstButton" actually have received the focus, but for some reason focus rectangle was not drawn. Can someone please explain and advise, why is this happening and how to fix it?

Developer technologies | Windows Presentation Foundation
Developer technologies | .NET | Other
Developer technologies | C#
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. gekka 12,206 Reputation points MVP Volunteer Moderator
    2023-10-12T10:55:51.14+00:00

    Default Focus Visual Style Behavior

    Focus visual styles act only when the focus action was initiated by the keyboard.

    Applying styles and triggers to buttons can change the visual on the focus.

    <ScrollViewer x:Name="scvApplications"
                    HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
        <DockPanel x:Name="pnlApplications" HorizontalAlignment="Left">
                        
            <Button  Content="TestButton">
                <Button.Style>
                    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
                        <Style.Triggers>
                            <Trigger Property="IsFocused" Value="true">
                                <Setter Property="BorderThickness" Value="2" />
                                <Setter Property="BorderBrush" Value="Black" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>
                        
        </DockPanel>
    </ScrollViewer>
    
    0 comments No comments

  2. Hui Liu-MSFT 48,681 Reputation points Microsoft External Staff
    2023-10-12T11:47:30.9+00:00

    Hi,@Ivan Pizhenko. Welcome Microsoft Q&A.

    This is due to the fact that you set the style AppButtonFocusStyle to the style of the FocusVisualStyle property. This is exactly the effect of the FocusVisualStyle property.

    FrameworkElement.FocusVisualStyle Property

    Gets or sets a property that enables customization of appearance, effects, or other style characteristics that will apply to this element when it captures keyboard focus.

    You could distinguish general styles and focus styles in styles and use them when creating buttons. You can update your code as follows:

     <Window.Resources>
          
            <Style x:Key="AppButtonFocusStyle" TargetType="Button">
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="SnapsToDevicePixels" Value="True"/>
                <Setter Property="Background" Value="green"/>
    
                <Style.Triggers>
                    <Trigger Property="IsFocused" Value="true">
                        <Setter Property="Background" Value="Red"/>
                        <Setter Property="BorderThickness" Value="4" />
                        <Setter Property="BorderBrush" Value="Black" />
                    </Trigger>
                </Style.Triggers>
            </Style>
    
        </Window.Resources>
        <Grid>
            <DockPanel >
             
                <ScrollViewer x:Name="scvApplications"     
                              HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
                    <DockPanel x:Name="pnlApplications" HorizontalAlignment="Left">
                        <Button Content="btntest" Width="100" Height="30" DockPanel.Dock="Right" Background="Red" Style="{StaticResource AppButtonFocusStyle}"  />
                    </DockPanel>
                </ScrollViewer>
            </DockPanel>
        </Grid>
    

    Codebehind:

    
      var appButton = new Button()
                        {
                            Name = $"btn{_nextAppButtonId++}",
                            Content = "some text on the button",
                            Background = Brushes.Transparent,
                                             Width=100,
                                             Height=40,
    
                            Style = (Style)FindResource("AppButtonFocusStyle"),
                            Tag = "something"
                        };
                    appButton.Click += ApplicationButton_Click;
                    pnlApplications.Children.Add(appButton);
                        Activate();
                        appButton.Focus();
                        appButton.UpdateLayout();
    
                    }
               
    
    
    

    The result:

    7


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  3. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.