为什么WPF IsKeyboardFocused提供虚假信息?

时间:2018-01-08 20:24:37

标签: 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?

1 个答案:

答案 0 :(得分:2)

你没有做错任何事;这是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触发器,并显示闪烁的插入符号,但键盘输入仍然发送到记事本。

这里的关键点是,只有当一个元素被赋予焦点而另一个应用程序处于活动状态时(因此是人为延迟)时才会出现问题。请注意,如果您使用SetFocusedElementKeyboard.Focus(_textBox)和其他版本替换_textBox.Focus()来电,问题仍然会出现。

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