18

I have created an UserControl which is loaded in a View (Window) in WPF. In my user control I have put a TextBox. I am unable to set focus on this text box when my view loads. I have tried following but nothing works for me:

  1. FocusManager.FocusedElement="{Binding ElementName=PwdBox}"

  2. I have created a FocusExtension to set focus on control.

Please help.

Palak.Maheria
  • 1,497
  • 2
  • 15
  • 32
  • 1
    Your first example code using `FocusManager` *should* work just fine, but we can't tell you what your problem is without seeing any code. However, if you are doing *both* 1 *and* 2, then maybe *that* is your problem? – Sheridan Oct 07 '13 at 12:59
  • Thanks Sheridan, but for #1 is all the code we require and for #2 I have referred following link http://stackoverflow.com/questions/5340543/wpf-mvvm-setting-ui-control-focus-from-viewmodel. And I am not using 1 and 2 both together. – Palak.Maheria Oct 07 '13 at 13:10

7 Answers7

19

This is similar to Sheridan's answer but does not require focus to be set to the control first. It fires as soon as the control is made visible and is based on the parent grid rather than the textbox itself.

In the 'Resources' section:

    <Style x:Key="FocusTextBox" TargetType="Grid">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=textBoxName, Path=IsVisible}" Value="True">
                <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=textBoxName}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

In my grid definition:

<Grid Style="{StaticResource FocusTextBox}" />
Anya Hope
  • 1,301
  • 1
  • 17
  • 33
  • 1
    This worked for me. A good edit to Sheridan's answer, but instead of typing out the element name, i just used "RelativeSource self", like so... {Binding RelativeSource={RelativeSource Self}} – EdwardM Jan 18 '16 at 19:12
  • To explain my scenario further, i used this to focus on an element inside of a TabItem, and it worked pefectly when it became visible – EdwardM Jan 18 '16 at 19:14
  • Good Improvisation. This trick worked for me when i was trying to set the focus of textbox in a Grid that was part of a User Control pop up. – iYadav Dec 13 '17 at 14:02
18

Another option that you have is to create a bool IsFocusedproperty in your view model. Then you can add a DataTrigger to set the focus when this property is true:

In a Resources section:

<Style x:Key="SelectedTextBoxStyle" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsFocused}" Value="True">
            <Setter Property="FocusManager.FocusedElement" 
                Value="{Binding RelativeSource={RelativeSource Self}}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

...

<TextBox Style="{StaticResource SelectedTextBoxStyle}" ... />

Note that at times, you may need to set it to false first to get it to focus (only when it is already true):

IsFocused = false;
IsFocused = true;
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • 1
    I have used FocusManager.FocusedElement on the text box control itself but it was not working, when I tried as shown above by Sheridan it worked, I don't know why but it works for me, thanks Sheridan. – Palak.Maheria Oct 08 '13 at 05:11
  • I'm sorry, but I can't seem to figure out how to get this to work. The style does't go in the textbox but it doesn't work anywhere else either. I'm stumped. – Tom Padilla May 13 '15 at 12:57
6

Register the Loaded-Event of your UserControl and set the Focus on your PwdBox by calling Focus() when your UserControl is loaded.

public class MyUserControl : UserControl{

  public MyUserControl(){
    this.Loaded += Loaded;
  }

  public void Loaded(object sender, RoutedEventArgs e){
    PwdBox.Focus();
    // or FocusManager.FocusedElement = PwdBox;
  }
}
Jehof
  • 34,674
  • 10
  • 123
  • 155
  • 1
    Thanks Jehof, but I do not want to write anything in code behind files. I want to do it in ViewModel or in xaml file. – Palak.Maheria Oct 07 '13 at 13:05
  • 2
    @Palak.Maheria I think you have no other way to focus an element when your UserControl is loaded. Using pur XAML will not solve your problem and using the ViewModel for this case is also not optimal, cause this is view logic and not relevant in the viewmodel – Jehof Oct 07 '13 at 13:09
  • @Palak.Maheria: if you don't want to write in code behind files, than you can use iteraction ands interactivity librarys and set loaded event this way – Sasha Oct 07 '13 at 13:13
  • 1
    @Jehof: ViewModels are ONLY about holding the view's logic... that's why its called VIEWModel (or PresentationModel). – Gope Feb 18 '14 at 17:09
3

Keyboard focus will be set when the FocusManager.FocusedElement property is set. Since the property is set when an element is initialized, this is often useful for setting initial focus.

However this is not quite the same thing as setting focus on load. If it is unloaded and reloaded, for example, the keyboard focus will not move the second time. The actual intended purpose of the FocusedElement property is for temporary focus scopes (for example, when a menu is opened, the FocusedElement of the window is kept separate from the keyboard focus because the menu is a separate focus scope -- and keyboard focus returns to the FocusedElement when the menu is closed). If you set FocusedElement on a Window, it will not persist -- since a Window is a focus scope, it will automatically update its FocusedElement whenever you move keyboard focus within it.

To set focus on the Loaded event (without using code-behind), this attached property should work for you:

public static class FocusExtensions {
    public static readonly DependencyProperty LoadedFocusedElementProperty =
        DependencyProperty.RegisterAttached("LoadedFocusedElement", typeof(IInputElement), typeof(FocusExtension),
                                            new PropertyMetadata(OnLoadedFocusedElementChanged));

    public static IInputElement GetLoadedFocusedElement(DependencyObject element) {
        return (IInputElement)element.GetValue(LoadedFocusedElementProperty);
    }

    public static void SetLoadedFocusedElement(DependencyObject element, bool value) {
        element.SetValue(LoadedFocusedElementProperty, value);
    }

    private static void OnLoadedFocusedElementChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
        var element = (FrameworkElement)obj;

        var oldFocusedElement = (IInputElement)e.OldValue;
        if (oldFocusedElement != null) {
            element.Loaded -= LoadedFocusedElement_Loaded;
        }

        var newFocusedElement = (IInputElement)e.NewValue;
        if (newFocusedElement != null) {
            element.Loaded += LoadedFocusedElement_Loaded;
        }
    }

    private static void LoadedFocusedElement_Loaded(object sender, RoutedEventArgs e) {
        var element = (FrameworkElement)sender;
        var focusedElement = GetLoadedFocusedElement(element);
        focusedElement.Focus();
    }
}

The usage is the same as FocusManager.FocusedElement, i.e.:

local:FocusExtensions.LoadedFocusedElement="{Binding ElementName=PwdBox}"
nmclean
  • 7,564
  • 2
  • 28
  • 37
3

It worked for me to simply add this attribute to the opening UserControl tag in my XAML:

FocusManager.FocusedElement="{Binding ElementName=DisplayName, Mode=OneTime}"

Where DisplayName is the name of the textbox I want to receive focus.

Andrew Arnott
  • 80,040
  • 26
  • 132
  • 171
  • I wonder why this is not the accepted answer? You just have to use FocusManager.FocusedElement on a higher control, for example the main Grid that contains the TextBox. – Alexandru Dicu Dec 11 '22 at 23:01
1

What i use in my authentication manager:

private void SelectLogicalControl()
{
    if (string.IsNullOrEmpty(TextboxUsername.Text))
        TextboxUsername.Focus();
    else
    {
        TextboxPassword.SelectAll();
        TextboxPassword.Focus();
    }
}

If no username is set, focus on the username-textbox; otherwise the (select all) passwordbox. This is in the codebehind-file, so not viewmodel ;)

Theike
  • 11
  • 2
0

On load event set the keyboard focus :

Keyboard.Focus(control);

Rankit Dua
  • 51
  • 6