11

在 WPF 程序中,我想获取当前(键盘)焦点,将其存储并稍后重新设置。

为了立即获得当前焦点,我使用:

DependencyObject focusScope = FocusManager.GetFocusScope(d);
_lastFocus = FocusManager.GetFocusedElement(focusScope);

稍后设置它我使用:

if (_lastFocus != null)
{
  IInputElement setFocus = _lastFocus;
  _lastFocus = null;
  d.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate
  {
    FocusManager.SetFocusedElement(d, setFocus);
  }));
}

这工作一次。但是,如果我再试一次,直到我重新创建我尝试将焦点设置到的有问题的对话框,它才会起作用,即使它做了同样的事情(我跟踪了获取和设置焦点)。相反,主窗口本身获得焦点。

我曾经听说WPF中有两种焦点,我是否也需要设置其他东西才能获得一致的结果?

4

2 回答 2

34

你是对的。WPF 具有您正在使用的逻辑焦点和键盘焦点。您可以在MSDN的Focus Overview页面中找到两者的完整详细信息。从该页面:

键盘焦点

键盘焦点是指当前正在接收键盘输入的元素。整个桌面上只能有一个元素具有键盘焦点。在 WPF 中,具有键盘焦点的元素将 IsKeyboardFocused 设置为 true。Keyboard 类的静态属性 FocusedElement 获取当前具有键盘焦点的元素。

为了使元素获得键盘焦点,基本元素上的 Focusable 和 IsVisible 属性必须设置为 true。某些类,例如 Panel 基类,默认将 Focusable 设置为 false;因此,如果您希望这样的元素能够获得键盘焦点,则必须将 Focusable 设置为 true。

键盘焦点可以通过用户与 UI 的交互来获得,例如标签到元素或在某些元素上单击鼠标。键盘焦点也可以通过使用 Keyboard 类的 Focus 方法以编程方式获得。Focus 方法尝试为指定元素提供键盘焦点。返回的元素是具有键盘焦点的元素,如果旧焦点对象或新焦点对象阻止请求,则该元素可能与请求的元素不同。

逻辑焦点

逻辑焦点是指焦点范围内的 FocusManager.FocusedElement。焦点范围是在其范围内跟踪 FocusedElement 的元素。当键盘焦点离开焦点范围时,焦点元素将失去键盘焦点但将保留逻辑焦点。当键盘焦点返回焦点范围时,获得焦点的元素将获得键盘焦点。这允许在多个焦点范围之间更改键盘焦点,但确保焦点范围内的焦点元素在焦点返回焦点范围时重新获得键盘焦点。

应用程序中可以有多个具有逻辑焦点的元素,但在特定焦点范围内可能只有一个元素具有逻辑焦点。

具有键盘焦点的元素对其所属的焦点范围具有逻辑焦点。


回到您的问题,您没有使用的另一种焦点是Keyboard.Focus. 你可以像这样使用它:

Keyboard.Focus(theButtonThatYouWantToFocus);

另外,请注意,该UIElement.Focus()方法将尝试将逻辑焦点键盘焦点设置为调用它的元素。如果将true 键盘焦点和逻辑焦点设置为此元素,并且false 仅将逻辑焦点设置为此元素,它将返回。


可用于集中控件的另一种方法是使用FocusManager.FocusedElement Attached Property. 大多数人静态使用它,在这种情况下,它只会在视图加载时工作一次:

<Grid FocusManager.FocusedElement="{Binding ElementName=TextBoxToFocus}">
    <TextBox Name="TextBoxToFocus" Text="Focus Me" />
<Grid>

但是,可以在 a 中使用它DataTrigger并将其设置为依赖于自定义bool属性,在此示例中,IsFocused属性:

<Style x:Key="FocusableTextBoxStyle" 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>

因此,每当我IsFocused从视图模型将属性设置为 true 时,应用此属性的任何元素Style都将获得逻辑焦点。现在很明显,这Style是用于TextBox控件的,但是如果您将其更改Control为例如,它仍然可以工作。

于 2013-10-10T08:27:37.017 回答
0

首先,您应该稍后使用Keyboard.ClearFocus()和编写。Keyboard.Focus("Your Input element")

Keyboard.ClearFocus()清除您的焦点参考。之后,您可以专注于界面的任何元素。

于 2017-09-14T08:00:40.820 回答