Search code examples
wpffocususer-controlsfocusmanager

Can't set focus to a child of UserControl


I have a UserControl which contains a TextBox. When my main window loads I want to set the focus to this textbox so I added Focusable="True" GotFocus="UC_GotFocus" to the UserControls definition and FocusManager.FocusedElement="{Binding ElementName=login}" to my main windows definition. In the UC_GotFocus method i simply call .Focus() on the control i want to focus on but this doesn't work.

All i need to do is have a TextBox in a UserControl receive focus when the application starts.

Any help would be appreciated, thanks.


Solution

  • I recently fixed this problem for a login splash screen that is being displayed via a storyboard when the main window is first loaded.

    I believe there were two keys to the fix. One was to make the containing element a focus scope. The other was to handle the Storyboard Completed event for the storyboard that was triggered by the window being loaded.

    This storyboard makes the username and password canvas visible and then fades into being 100% opaque. The key is that the username control was not visible until the storyboard ran and therefore that control could not get keyboard focus until it was visible. What threw me off for awhile was that it had "focus" (i.e. focus was true, but as it turns out this was only logical focus) and I did not know that WPF had the concept of both logical and keyboard focus until reading Kent Boogaart's answer and looking at Microsoft's WPF link text

    Once I did that the solution for my particular problem was straightforward:

    1) Make the containing element a focus scope

    <Canvas FocusManager.IsFocusScope="True" Visibility="Collapsed">
        <TextBox x:Name="m_uxUsername" AcceptsTab="False" AcceptsReturn="False">
        </TextBox>
    </Canvas>
    

    2) Attach a Completed Event Handler to the Storyboard

        <Storyboard x:Key="Splash Screen" Completed="UserNamePassword_Storyboard_Completed">
    ...
    </Storyboard>
    

    and

    3) Set my username TextBox to have the keyboard focus in the storyboard completed event handler.

    void UserNamePassword_Storyboard_Completed(object sender, EventArgs e)
    {
     m_uxUsername.Focus();
    }
    

    Note that calling item.Focus() results in the call Keyboard.Focus(this), so you don't need to call this explicitly. See this question about the difference between Keyboard.Focus(item) and item.Focus.