Keyboard.Focus 不适用于 WPF 中的文本框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13955340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:41:38  来源:igfitidea点击:

Keyboard.Focus does not work on text box in WPF

c#wpfxamltextboxfocus

提问by legrandviking

I am banging my head on what looks like such a simple problem to fix in wpf but i have yet to discover why i can't get my app to behave according to my plan.

我正在考虑在 wpf 中解决一个看起来如此简单的问题,但我还没有发现为什么我的应用程序无法按照我的计划运行。

I have a small search box that pops-up in my wpf application when user presses ctrl+f. All i want is for the caret to be flashing inside the search box text box, ready to take whatever user input without the user having to click on it. Here is the xaml code for the text box which is visible, enabled, hit testable, tabstopable and focusable.

当用户按下 ctrl+f 时,我的 wpf 应用程序中会弹出一个小的搜索框。我想要的是插入符号在搜索框文本框中闪烁,准备好接受任何用户输入,而无需用户点击它。这是文本框的 xaml 代码,它是可见的、已启用的、可点击测试的、可制表的和可聚焦的。

   <TextBox x:Name="SearchCriteriaTextBox" Text="{Binding SearchCriteria}" Focusable="True" IsEnabled="True" IsTabStop="True" IsHitTestVisible="True" Style="{DynamicResource SearchTextBoxStyle}" Grid.Column="1" Margin="5,10,0,5" />

In the code behind, i have this method called when the visibility of the search box is affected. the search box is loaded at the start of the app.

在后面的代码中,当搜索框的可见性受到影响时,我会调用此方法。搜索框在应用程序开始时加载。

    /// <summary>
    /// Handles events triggered from focusing on this view.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="dependencyPropertyChangedEventArgs">The key event args.</param>
    private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        if (!((bool) dependencyPropertyChangedEventArgs.NewValue))
        {
            return;
        }

        SearchCriteriaTextBox.Focus();
        Keyboard.Focus(SearchCriteriaTextBox);
        SearchCriteriaTextBox.Select(0, 0);

        if (SearchCriteriaTextBox.Text.Length > 0)
        {
            SearchCriteriaTextBox.SelectAll();
        }
    }

The problem is, code gets called, component becomes IsFocused=true but does not gain keyboard focus. Am I missing something? Unless another control keeps hold ferociously to the keyboard focus which i am pretty sure i didn't code, why would this piece of rather simple code would not work properly.

问题是,代码被调用,组件变为 IsFocused=true 但没有获得键盘焦点。我错过了什么吗?除非另一个控件保持凶猛的键盘焦点,我很确定我没有编码,为什么这段相当简单的代码不能正常工作。

回答by Rachel

As a workaround, you could try using the Dispatcherto set the focus at a later DispatcherPriority, such as Input

作为一种解决方法,您可以尝试使用Dispatcher将焦点设置在稍后的DispatcherPriority,例如Input

Dispatcher.BeginInvoke(DispatcherPriority.Input,
    new Action(delegate() { 
        SearchCriteriaTextBox.Focus();         // Set Logical Focus
        Keyboard.Focus(SearchCriteriaTextBox); // Set Keyboard Focus
     }));

From the description of your problem, it sounds like you don't have Keyboard focus set. WPF can have multiple Focus Scopes, so multiple elements can have Logical Focus (IsFocused = true), however only one element can have Keyboard Focus and will receive keyboard input.

从您的问题描述来看,您似乎没有设置键盘焦点。WPF 可以有多个焦点范围,因此多个元素可以有逻辑焦点 ( IsFocused = true),但是只有一个元素可以有键盘焦点并接收键盘输入。

The code you posted should set the focus correctly, so something must be occurring afterwards to move Keyboard Focus out of your TextBox. By setting focus at a later dispatcher priority, you'll be ensuring that setting keyboard focus to your SearchCriteriaTextBoxgets done last.

您发布的代码应该正确设置焦点,因此之后必须发生某些事情才能将键盘焦点移出TextBox. 通过在稍后的调度程序优先级设置焦点,您将确保将键盘焦点设置为SearchCriteriaTextBox最后完成。

回答by Cristian G

If it helps anyone I had this problem and my application had a main window with multiple user controls placed in separate grids with a visibility data binding. Because the grids were there when the application was built the .Focus() called on Loaded or Constructor would be called at the build time, not at visibility time.

如果它可以帮助我遇到这个问题的任何人,并且我的应用程序有一个主窗口,其中多个用户控件放置在具有可见性数据绑定的单独网格中。因为在构建应用程序时网格就在那里,所以在 Loaded 或 Constructor 上调用的 .Focus() 将在构建时调用,而不是在可见时调用。

Anyhow I fixed it by calling .Focus() on MouseEnter event of the grid. Works fine for me.

无论如何,我通过在网格的 MouseEnter 事件上调用 .Focus() 来修复它。对我来说很好用。

回答by Neil Dandekar

Building on Rachel's solution there is a simpler way.

基于 Rachel 的解决方案,有一种更简单的方法。

in XAML add to the TextBox Loaded="Got_Loaded"

在 XAML 中添加到 TextBox Loaded="Got_Loaded"

and in code behind

并在后面的代码中

    private void Got_Loaded(object sender, RoutedEventArgs e)
    {
        Keyboard.Focus(((TextBox)sender));
    }