WPF 中,有两个与焦点有关的主要概念:键盘焦点逻辑焦点。 键盘焦点指接收键盘输入的元素,而逻辑焦点指焦点范围中具有焦点的元素。 本概述将详细介绍这些概念。 理解这些概念之间的区别对于创建具有可以获取焦点的多个区域的复杂应用程序是非常重要的。

参与焦点管理的主要类有 Keyboard 类、FocusManager 类以及基元素类(如 UIElementContentElement)。 有关基元素的更多信息,请参见基元素概述

Keyboard 类主要与键盘焦点相关,而 FocusManager 则与逻辑焦点相关,但这种区别不是绝对的。 具有键盘焦点的元素也将具有逻辑焦点,但具有逻辑焦点的元素不一定具有键盘焦点。 当您使用 Keyboard 类来设置具有键盘焦点的元素时,这一点是很明显的,因为它还在元素上设置逻辑焦点。

键盘焦点


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

为了使元素能够获取键盘焦点,基元素的 FocusableIsVisible 属性必须设置为 true。 有些类(如 Panel 基类)默认情况下将 Focusable 设置为 false;因此,如果您希望此类元素能够获取键盘焦点,必须将 Focusable 设置为 true。

可以通过用户与 UI 交互(例如,按 Tab 键定位到某个元素或者在某些元素上单击鼠标)来获取键盘焦点。 还可以通过使用 Keyboard 类的 Focus 方法,以编程方式获取键盘焦点。 Focus 方法尝试将键盘焦点给予指定的元素。 返回的元素是具有键盘焦点的元素,如果有旧的或新的焦点对象阻止请求,则具有键盘焦点的元素可能不是所请求的元素。

下面的示例使用 Focus 方法在 Button 上设置键盘焦点。

 
 

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

基元素类的 IsKeyboardFocused 属性获取一个指示元素是否具有键盘焦点的值。 基元素类的 IsKeyboardFocusWithin 属性获取一个指示元素或者它的任何一个可视子元素是否具有键盘焦点的值。

当在应用程序启动时设置初始焦点时,接收焦点的元素必须连接到一个 PresentationSource,并且该元素必须将 FocusableIsVisible 设置为 true。 设置初始焦点的推荐位置是在 Loaded 事件处理程序中。 还可以通过调用 InvokeBeginInvoke 来使用 Dispatcher 回调。

逻辑焦点


逻辑焦点指焦点范围中的 FocusManager

.FocusedElement。 焦点范围是一个跟踪其范围内的 FocusedElement 的元素。 当键盘焦点离开焦点范围时,焦点元素会失去键盘焦点,但保留逻辑焦点。 当键盘焦点返回到焦点范围时,焦点元素会再次获得键盘焦点。 这使得键盘焦点可以在多个焦点范围之间切换,但确保了在焦点返回到焦点范围时,焦点范围中的焦点元素再次获得键盘焦点。

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

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

在可扩展应用程序标记语言 (XAML) 中,可以通过将 FocusManager 附加属性 IsFocusScope 设置为 true,将元素转变为焦点范围。 在代码中,可以通过调用 SetIsFocusScope 将元素转变为焦点范围。

下面的示例通过设置 IsFocusScope 附加属性将 StackPanel 转变为焦点范围。

<StackPanel Name="focusScope1" FocusManager.IsFocusScope="True" Height="200" Width="200"> <Button Name="button1" Height="50" Width="50"/> <Button Name="button2" Height="50" Width="50"/></StackPanel>
 
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

GetFocusScope 返回指定元素的焦点范围。

WPF 中默认情况下即为焦点范围的类有 WindowMenuItemToolBarContextMenu

GetFocusedElement 获取指定焦点范围的焦点元素。SetFocusedElement 设置指定焦点范围中的焦点元素。SetFocusedElement 通常用于设置初始焦点元素。

下面的示例设置焦点范围中的焦点元素并获取焦点范围的焦点元素。

 
 

// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);

// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);

键盘导航


当按下导航键之一时,KeyboardNavigation 类将负责实现默认键盘焦点导航。 导航键有:Tab、Shift+Tab、Ctrl+Tab、Ctrl+Shift+Tab、向上键、向下键、向左键和向右键。

可以通过设置附加的 KeyboardNavigation 属性 TabNavigationControlTabNavigationDirectionalNavigation 来更改导航容器的导航行为。 这些属性是 KeyboardNavigationMode 类型,可能值有 ContinueLocalContainedCycleOnce 以及 None。 默认值是 Continue,这意味着元素不是导航容器。

下面的示例创建包含许多 MenuItem 对象的 MenuMenuTabNavigation 附加属性设置为 Cycle。 当使用 Tab 键在 Menu 中改变焦点时,焦点将从每个元素上移过,当到达最后一个元素后会返回第一个元素。

 
 

<Menu KeyboardNavigation.TabNavigation="Cycle">
  <MenuItem Header="Menu Item 1" />
  <MenuItem Header="Menu Item 2" />
  <MenuItem Header="Menu Item 3" />
  <MenuItem Header="Menu Item 4" />
</Menu>

 
 

Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();

navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);

KeyboardNavigation.SetTabNavigation(navigationMenu,   KeyboardNavigationMode.Cycle);

以编程方式定位焦点


处理焦点的其他 API 有 MoveFocusPredictFocus

MoveFocus 将焦点移到应用程序中的下一个元素。 TraversalRequest 用于指定方向。 传递给 MoveFocusFocusNavigationDirection 指定焦点可以移动的不同方向,如 FirstLastUpDown

下面的示例使用 MoveFocus 来改变焦点元素。 有关此示例的完整源代码,请参见以编程方式操作焦点示例

 
 

// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;

// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);

// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

// Change keyboard focus.
if (elementWithFocus != null)
{
    elementWithFocus.MoveFocus(request);
}

PredictFocus 返回当要改变焦点时将接收焦点的对象。 当前,PredictFocus 仅支持 UpDownLeft 以及 Right

焦点事件


与键盘焦点相关的事件有 PreviewGotKeyboardFocusGotKeyboardFocusPreviewLostKeyboardFocus 以及 LostKeyboardFocus。 这些事件定义为 Keyboard 类的附加事件,但更便于作为基元素类上的等效路由事件来访问。 有关事件的更多信息,请参见路由事件概述

当元素获取键盘焦点时,会引发 GotKeyboardFocus。当元素失去键盘焦点时,会引发 LostKeyboardFocus。 如果处理了 PreviewGotKeyboardFocus 事件或 PreviewLostKeyboardFocusEvent 事件,并且 Handled 设置为 true,则焦点将不会改变。

下面的示例将 GotKeyboardFocusLostKeyboardFocus 事件处理程序附加到 TextBox

 
 

<Border BorderBrush="Black" BorderThickness="1"
        Width="200" Height="100" Margin="5">
  <StackPanel>
    <Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
    <TextBox Width="175"
             Height="50"
             Margin="5"
             TextWrapping="Wrap"
             HorizontalAlignment="Center"
             VerticalScrollBarVisibility="Auto"
             GotKeyboardFocus="TextBoxGotKeyboardFocus"
             LostKeyboardFocus="TextBoxLostKeyboardFocus"
             KeyDown="SourceTextKeyDown"/>
  </StackPanel>
</Border>

TextBox 获取键盘焦点时,TextBoxBackground 属性会改为 LightBlue

 
 

private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

if (source != null)
    {
        // Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue;

// Clear the TextBox.
        source.Clear();
    }
}

TextBox 失去键盘焦点时,TextBoxBackground 属性会重新改为 white。

 
 

private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

if (source != null)
    {
        // Change the TextBox color when it loses focus.
        source.Background = Brushes.White;

// Set the  hit counter back to zero and updates the display.
        this.ResetCounter();
    }
}

与逻辑焦点有关的事件有 GotFocusLostFocus。 这些事件在 FocusManager 上定义为附加事件,但 FocusManager 不公开 CLR 事件包装。UIElementContentElement 可以更方便地公开这些事件。

文章来源   http://zwkufo.blog.163.com/blog/static/2588251201042014725122/

[转]WPF焦点概述的更多相关文章

  1. 微软原文翻译:适用于.Net Core的WPF数据绑定概述

    原文链接,大部分是机器翻译,仅做了小部分修改.英.中文对照,看不懂的看英文. Data binding overview in WPF 2019/09/19 Data binding in Windo ...

  2. wpf动画概述

    http://msdn.microsoft.com/zh-cn/library/vstudio/ms752312(v=vs.100).aspx Windows Presentation Foundat ...

  3. WPF学习概述

    引言 在桌面开发领域,虽然在某些领域,基于electron的跨平台方案能够为我们带来某些便利,但是由于WPF技术能够更好的运用Direct3D带来的性能提升.以及海量Windows操作系统和硬件资源的 ...

  4. WPF 一 概述

    创建一个项目吧 菜单>文件>新建>项目 看一看目录结构 WPF应用程序”会在“引用”里面自动添加下图中所示的 PresentationCore.PresentationFramewo ...

  5. [WPF 自定义控件]让Form在加载后自动获得焦点

    1. 需求 加载后让第一个输入框或者焦点是个很基本的功能,典型的如"登录"对话框.一般来说"登录"对话框加载后"用户名"应该马上获得焦点,用 ...

  6. [WPF自定义控件库] 让Form在加载后自动获得焦点

    原文:[WPF自定义控件库] 让Form在加载后自动获得焦点 1. 需求 加载后让第一个输入框或者焦点是个很基本的功能,典型的如"登录"对话框.一般来说"登录" ...

  7. WPF 程序如何跨窗口/跨进程设置控件焦点

    原文:WPF 程序如何跨窗口/跨进程设置控件焦点 WPF 程序提供了 Focus 方法和 TraversalRequest 来在 WPF 焦点范围内转移焦点.但如果 WPF 窗口中嵌入了其他框架的 U ...

  8. WPF 中的形状和基本绘图概述

    本主题概述如何使用 Shape 对象绘图. Shape 是一种允许您在屏幕中绘制形状的 UIElement 类型. 由于它们是 UI 元素,因此 Shape 对象可以在 Panel 元素和大多数控件中 ...

  9. WPF从入门到放弃系列第一章 初识WPF

    什么是WPF WPF(Windows Presentation Foundation)是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分.它提供 ...

随机推荐

  1. [JZOJ3339]【NOI2013模拟】wyl8899和法法塔的游戏

    题目 题目大意 给你一个数列,每次给出\(r,a,b\),你要找到\(l\in [a,b]\)使得\([l,r-1]\)的异或和最小, 并且要修改\(r\)位置的数. 思考历程 当我看到这题的时候,已 ...

  2. redis可视化客户端工具TreeNMS

    TreeNMS是一款redis,Memcache可视化客户端工具,采用JAVA开发,实现基于WEB方式对Redis, Memcached数据库进行管理.维护. 功能包括:状态参数监控,NoSQL数据库 ...

  3. Mybatis笔记 – 入门程序开发

    一.Mybatis开发环境 JDK:jdk_1.7 Eclipse:Oxygen.1 Release (4.7.1) MySQL:MySQL Servr 5.7 1.添加相关ja r包 mybatis ...

  4. Docker系列(六):Docker网络机制(下)

    Linux Namespace详解 namespace:是一个空间,空间里可以放进程,文件系统,账号,网络等,某个资源被放到namespace之后 别人就看不到他了. 可以看到有两个namespace ...

  5. selector是在文件夹drawable中进行定义的xml文件转载 https://www.cnblogs.com/fx2008/p/3157040.html

    获取Drawable对象: Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable ...

  6. PAT甲级——A1127 ZigZagging on a Tree【30】

    Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can ...

  7. PAT甲级——A1115 Counting Nodes in a BST【30】

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  8. 第一篇:spring+springMVC项目启动最终笔记(一web.xml)

    1.web应用启动从web.xml开始,首先创建一个全局的上下文(Context),名字叫ServletContext,可以理解为一间图书馆,或一个数据结构(如map,但是比map牛多了),整个结构类 ...

  9. ssm项目中使用拦截器加上不生效解决方案

    在很多时候,需要拦截器来帮助我们完成一些特定的工作,比如获取请求的参数,本身在request这种获取数据就是一次磁盘的io, 如果在filter中获取了参数,那么在controller中就不能获取相关 ...

  10. 执行sql查询,并查看语句执行花费时间

    declare @d datetimeset @d=getdate() select * from A PRINT '[语句执行花费时间(毫秒)]'+LTRIM(datediff(ms,@d,getd ...