3
votes

I have a WPF Window in which I have added a button. I want the button should have the keyboard focus with dotted border around it when the application starts up (basically when the window is activated). Normally we see the dotted border when we navigate through controls using Tab key.

I tried the following code but still i think I am missing something.

XAML

<Window x:Class="PropertyChangedTest.TestPropertyChangedWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Activated="Window_Activated">
    <StackPanel Name="justPanel">
        <Button Content="Hello" x:Name="Btn" Height="23" Width="52" Focusable="True" IsDefault="True" Click="Btn_Click"></Button>
    </StackPanel>
</Window>

.cs file

private void Window_Activated(object sender, EventArgs e)
{
    if (!bActivatedOnce)
    {
       bool bVisible = Btn.IsVisible;
       UIElement elementWithFo = Keyboard.Focus(Btn) as UIElement;
       bActivatedOnce = true;             
    }
}  

The button has the keyboard focus but it doesnt have the dotted border around it. When i press Alt key the dotted border appears around the button.

2

2 Answers

2
votes

This problem is quite the same as this. Please see my answer there.

The problem is that the dotted border only appears if you are navigating by keyboard.

0
votes

By editing the KeyboardNavigationEx file from ControlzEx I managed to solve the issue (full credit goes, as always, to punker76).

Just call the KeyboardHelper.Focus method passing the UIElement that shoud be focused. Here's how it'd look in your case:

private void Window_Activated(object sender, EventArgs e)
{
    if (!bActivatedOnce && Btn.IsVisible)
    {
       KeyboardHelper.Focus(Btn);

       bActivatedOnce = true;             
    }
}  

And here's the KeyboardHelper class:

public sealed class KeyboardHelper
{
    private static KeyboardHelper _Instance;

    private readonly PropertyInfo _AlwaysShowFocusVisual;
    private readonly MethodInfo _ShowFocusVisual;

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static KeyboardHelper()
    {
    }

    private KeyboardHelper()
    {
        var type = typeof(KeyboardNavigation);

        _AlwaysShowFocusVisual = type.GetProperty("AlwaysShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
        _ShowFocusVisual = type.GetMethod("ShowFocusVisual", BindingFlags.NonPublic | BindingFlags.Static);
    }

    internal static KeyboardHelper Instance => _Instance ?? (_Instance = new KeyboardHelper());

    internal void ShowFocusVisualInternal()
    {
        _ShowFocusVisual.Invoke(null, null);
    }

    internal bool AlwaysShowFocusVisualInternal
    {
        get { return (bool)_AlwaysShowFocusVisual.GetValue(null, null); }
        set { _AlwaysShowFocusVisual.SetValue(null, value, null); }
    }

    public static void Focus(UIElement element)
    {
        element?.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
        {
            var keybHack = KeyboardHelper.Instance;
            var oldValue = keybHack.AlwaysShowFocusVisualInternal;

            keybHack.AlwaysShowFocusVisualInternal = true;

            try
            {
                Keyboard.Focus(element);
                keybHack.ShowFocusVisualInternal();
            }
            finally
            {
               keybHack.AlwaysShowFocusVisualInternal = oldValue;
            }
        }));
    }
}