c# - 为什么 WPF IsKeyboardFocused 提供错误信息?

标签 c# wpf

我尝试遵循此问题的答案中描述的模式。 How to set focus to textbox using MVVM?

但是,我对键盘焦点的概念遇到了麻烦。如果我有记事本或其他应用程序与我的 WPF 应用程序同时运行,并单击记事本将键盘焦点放在那里,然后执行某些操作使我的其他应用程序将焦点放入其文本框之一,然后触发给出了我的应用程序的文本框现在具有键盘焦点的视觉提示。然而,当我开始打字时,我发现情况并非如此,因为文本实际上进入了记事本。

这是我的触发器的 xaml。

<TextBox.Style>
    <Style TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ReadyForDataEntry}" Value="True">
                <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}" />
           </DataTrigger>
            <Trigger Property="IsKeyboardFocused" Value="true">
                <Setter Property="Background" Value="Lavender"/>
                <Setter Property="BorderBrush" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
 </Style>

本质上,文本框有时会亮起边框和背景颜色,表明该文本框的 IsKeyboardFocused = true,即使最后单击的任何应用程序(例如,一个笔记、记事本)都会接收键盘输入。什么是我失踪了?当键盘焦点显然根本不正确时,为什么 WPF 控件将 IsKeyboardFocused 设置为 true?

最佳答案

你没有做错任何事;这是 WPF 的一个已知怪癖。

当控件接收到逻辑焦点时,WPF 也会尝试为其提供键盘焦点。 但是,当您在非事件 WPF 应用程序中分配键盘焦点时,该应用程序的行为就像它事件一样。这意味着,除其他外,聚焦的 TextBox 将显示闪烁的插入符号,并且 IsKeyboardFocused 和相关属性将被设置。

我过去见过这个问题,重现起来很简单。

Xaml:

<Window x:Class="WpfTest.FocusTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid>
    <StackPanel HorizontalAlignment="Center"
                VerticalAlignment="Center">
      <TextBox x:Name="_textBox"
               Width="150">
        <TextBox.Style>
          <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
              <Trigger Property="IsKeyboardFocused"
                       Value="true">
                <Setter Property="Background"
                        Value="Lavender" />
                <Setter Property="BorderBrush"
                        Value="Blue" />
              </Trigger>
            </Style.Triggers>
          </Style>
        </TextBox.Style>
      </TextBox>
      <Button Margin="0,7,0,0"
              Content="_Click Me"
              Click="OnButtonClick" />
    </StackPanel>
  </Grid>
</Window>

隐藏代码:

public partial class FocusTest
{
    public FocusTest()
    {
        InitializeComponent();
    }

    private void OnButtonClick(object sender, RoutedEventArgs e)
    {
        _textBox.Text = "";

        // NOTE: Requires System.Reactive.Core, available in NuGet.
        System.Reactive.Concurrency.Scheduler.Default.Schedule(
            TimeSpan.FromSeconds(5),
            () => this.Dispatcher.BeginInvoke(new Action(this.SetFocus)));
    }

    private void SetFocus()
    {
        _textBox.Text = "Focused";
        FocusManager.SetFocusedElement(_textBox, _textBox);
    }
}

按按钮,Alt+Tab 转到记事本,然后等待 5 秒钟,让 TextBox 接收焦点。 IsKeyboardFocused 触发器被触发,并且出现闪烁的插入符号,但键盘输入仍然发送到记事本。

这里的关键点是,只有当一个元素获得焦点而另一个应用程序处于事件状态时才会出现问题(因此存在人为延迟)。请注意,如果将 SetFocusedElement 调用替换为 Keyboard.Focus(_textBox)_textBox.Focus() 和其他变体,问题仍然会出现.

不幸的是,我不知道有一种可靠的、非黑客的方法来解决这个问题。我不记得我在这上面花了多少时间,但我最终认为这不值得这么麻烦。这只是不经常出现的事情。

关于c# - 为什么 WPF IsKeyboardFocused 提供错误信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48157550/

相关文章:

c# - UWP 从任务更新 UI

c# - StructureMap 可以返回特例吗?

c# - Linq 到 NHibernate : sum of sums

c# - 哪种方式更好?将媒体文件作为字节数组还是字符串保存到 MongoDB?

c# - 垃圾收集器的替代品是什么?

c# - Socket 的扩展方法内存泄漏 'ReceiveAsync' !

wpf - 设计器无法在窗口自定义控件上获得良好的样式

wpf - 在 WPF 应用程序中使用 ASP.NET MVC Controller 操作

c# - 悬停 ComboBox 时更改 ComboBoxItem 的前景色

wpf - 在无边框 WPF 窗口上启用 Vista 玻璃效果