简体   繁体   English

在WPF中的UserControl中将焦点设置在文本框控件上

[英]Set focus on a textbox control in UserControl in wpf

I have created an UserControl which is loaded in a View (Window) in WPF. 我创建了一个UserControl ,该UserControl已加载到WPF的一个View(窗口)中。 In my user control I have put a TextBox . 在我的用户控件中,我放置了一个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. 我创建了一个FocusExtension以将焦点放在控件上。

Please help. 请帮忙。

This is similar to Sheridan's answer but does not require focus to be set to the control first. 这类似于Sheridan的答案,但不需要首先将焦点设置为控件。 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}" />

Another option that you have is to create a bool IsFocused property in your view model. 您拥有的另一个选择是在视图模型中创建bool IsFocused属性。 Then you can add a DataTrigger to set the focus when this property is true : 然后,可以在此属性为true时添加DataTrigger来设置焦点:

In a Resources section: Resources部分中:

<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 ): 请注意,有时可能需要先将其设置为false才能使其聚焦(仅当它已经为true ):

IsFocused = false;
IsFocused = true;

Keyboard focus will be set when the FocusManager.FocusedElement property is set. 设置FocusManager.FocusedElement属性时,将设置键盘焦点。 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). FocusedElement属性的实际预期目的是用于临时焦点范围(例如,打开菜单时,窗口的FocusedElement与键盘焦点保持分开,因为菜单是单独的焦点范围-键盘焦点返回到关闭菜单时的FocusedElement)。 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. 如果在Window上设置FocusedElement,则它将不会持久-由于Window是焦点范围,因此只要您在其中移动键盘焦点,它就会自动更新其FocusedElement。

To set focus on the Loaded event (without using code-behind), this attached property should work for you: 若要将焦点放在Loaded事件上(不使用后台代码),此附加属性应为您工作:

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 , ie: 用法与FocusManager.FocusedElement相同,即:

local:FocusExtensions.LoadedFocusedElement="{Binding ElementName=PwdBox}"

Register the Loaded-Event of your UserControl and set the Focus on your PwdBox by calling Focus() when your UserControl is loaded. 注册您的UserControl的Loaded-Event ,并在加载 UserControl时通过调用Focus()在PwdBox上设置Focus。

public class MyUserControl : UserControl{

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

  public void Loaded(object sender, RoutedEventArgs e){
    PwdBox.Focus();
    // or FocusManager.FocusedElement = PwdBox;
  }
}

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 ;) 这是在代码隐藏文件中,因此不是viewmodel;)

It worked for me to simply add this attribute to the opening UserControl tag in my XAML: 对我来说,只需将此属性添加到XAML中的开头UserControl标记即可:

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

Where DisplayName is the name of the textbox I want to receive focus. 其中DisplayName是我希望获得焦点的文本框的名称。

加载事件时,设置键盘焦点:

Keyboard.Focus(control);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM