本文介绍在 MVVM 中,如何用 ViewModel 控制焦点。

这焦点设置个东西嘛,有些争论。就是到底要不要用 ViewModel 来控制视图的键盘输入焦点。这里不讨论,假设你就是要通过 VM,设置输入焦点在哪里。

MSDN 有解释关于 Focus 的,还有 FocusManager,点击这里打开。不知道的话建议你先看看,只求结果的可以直接看下面代码,抄就是了。这次,初级的解释全部略过,直接说做法,看不懂的请留言。做法很多,大概两种比较符合 MVVM 模式:

1. DataTrigger 设置 FocusedElement

Style 中写 Trigger,DataTrigger,值变化触发设置 FocusManager 的 FocusedElement。

XAML:

<Grid><Grid.Style><Style><Style.Triggers><DataTrigger Binding="{Binding Path=ScanFtBarCodeNow}" Value="True"><Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=FtNoTextBox}"/></DataTrigger></Style.Triggers></Style></Grid.Style><TextBox name="FtNoTextBox"/></Grid>

注意:放置 Style 的位置要注意。一层又一层 Grid 的话,FocusManager 单单设置 FocusedElement 为 TextBox 不足够。原因在 MSDN 有说明,不重复。

2. Attached Property

使用 Attached Property 为控件加属性,值变化触发 CallBack,然后 UIElement.Focus()。所谓值变化,比如,bool 变为 True 。

CODE:

publicstaticclass FocusBehavior {publicstaticbool GetIsFocused(DependencyObject obj) {return (bool)obj.GetValue(IsFocusedProperty);}publicstaticvoid SetIsFocused(DependencyObject obj, bool value) {obj.SetValue(IsFocusedProperty, value);}publicstaticreadonly DependencyProperty IsFocusedProperty =DependencyProperty.RegisterAttached("IsFocused", typeof(bool),typeof(FocusBehavior),new UIPropertyMetadata(false, (s, e) => {var sender = (UIElement)s;if ((bool)e.NewValue) {sender.Focus();Keyboard.Focus(sender);}}));
}

XAML:

<TextBox local:FocusBehavior.IsFocused="{Binding Path=ScanBarCodeNow}"/>

这做法虽然简单,但实际绑定的并非 UIElement.IsFocused 这只读属性,看CallBack 代码就知道,两个Focus() 都只是方法。界面操作焦点离开此控件时候,DependencyProperty 的值不会变化。后果是,设置一次 true 后,属性值 true,焦点离开它依然是 true,你再设置它 true,会被认定为值无变化,CallBack 没有执行,Focus() 不会运行。Workaround:先设 false 再设 true。

好傻吧。改一下,虽然 IsFocus 是只读无法直接绑定去改它,但可以把 GotFocus 和 LostFocus 事件接上此 Attached Property,触发变更 DependencyProperty 的值,使它变成双向绑定。

using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;namespace Lepton_Practical_MVVM_5 {publicstaticclass FocusBehavior {privatestatic Dictionary<UIElement, RoutedEventHandler> handlers =new Dictionary<UIElement, RoutedEventHandler>();publicstaticbool? GetIsFocused(DependencyObject obj) {return (bool?)obj.GetValue(IsFocusedProperty);}publicstaticvoid SetIsFocused(DependencyObject obj, bool? value) {obj.SetValue(IsFocusedProperty, value);}publicstaticreadonly DependencyProperty IsFocusedProperty =DependencyProperty.RegisterAttached("IsFocused",typeof(bool?),typeof(FocusBehavior),new UIPropertyMetadata() {DefaultValue =null,PropertyChangedCallback =(s, e) => {UIElement sender = (UIElement)s;RoutedEventHandler x;if (!handlers.TryGetValue(sender, out x)) {Attach(sender);}if ((bool)e.NewValue) {sender.Focus();Keyboard.Focus(sender);}}});privatestaticvoid Attach(UIElement sender) {RoutedEventHandler handler = (s, e) => {UIElement ui = (UIElement)s;if (e.RoutedEvent == UIElement.GotFocusEvent) {ui.SetValue(IsFocusedProperty, true);}if (e.RoutedEvent == UIElement.LostFocusEvent) {ui.SetValue(IsFocusedProperty, false);}};sender.GotFocus += handler;sender.LostFocus += handler;handlers.Add(sender, handler);}}
}

Dictionary 为了记下已连接的 Handler ,以免重复加入。

XAML:

<Window x:Class="Lepton_Practical_MVVM_5.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Lepton_Practical_MVVM_5"Title="MainWindow" Height="350" Width="525"><Grid><TextBox local:FocusBehavior.IsFocused="{Binding Path=IsTextBox1Focus,Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="49,54,0,0" Name="textBox1" VerticalAlignment="Top" Width="120"/></Grid></Window>

点击这里下载Attached Property 版本的代码。

这做法是只有加句柄没有移除,你有情况需要移除的话,自己改吧。

我在这群里,欢迎加入交流:
开发板玩家群 578649319
硬件创客 (10105555)

转载于:https://www.cnblogs.com/leptonation/p/3292961.html

C# WPF MVVM 实战 – 5- 用绑定,通过 VM 设置 View 的控件焦点相关推荐

  1. C# WPF MVVM 实战 – 3 – 树结构

    树结构放在 WPF ,有大家熟悉的 TreeView.Menu / MenuItem 等等,自定义的话它是 HierarchicalDataTemplate. 用上 MVVM 模式,视图与数据分离,意 ...

  2. Photoshop和WPF双剑配合,打造炫酷个性的进度条控件

    现在如果想打造一款专业的App,UI的设计和操作的简便性相当重要.UI设计可以借助Photoshop或者AI等设计工具,之前了解到WPF设计工具Expression Blend可以直接导入PSD文件或 ...

  3. android如何绑定事件,Android_安卓为按钮控件绑定事件的五种方式

    一.写在最前面 本次,来介绍一下安卓中为控件--Button绑定事件的五种方式. 二.具体的实现 第一种:直接绑定在Button控件上: 步骤1.在Button控件上设置android:onClick ...

  4. PyQt5实战之二维码生成器(二):控件功能实现

    前言 经过上一章,我们构建了二维码生成器的基本界面,本章将实现界面中各个控件的功能. 文章目录 一.工具箱的数据输入 二.颜色选项卡 三.图像选项卡 四.菜单栏 五.状态栏 六.回顾 \_\_init ...

  5. repeater 控件ajax绑定数据源,用 DataList 和 Repeater 控件显示数据(C#) | Microsoft Docs...

    使用 DataList 和 Repeater 控件显示数据 (C#) 09/13/2006 本文内容 在前面的教程中,我们使用了 GridView 控件来显示数据. 从本教程开始,我们将介绍如何生成包 ...

  6. WPF中如何将List<string>数据绑定到DataGrid控件中

    一,前端 <DataGrid x:Name="Onlinedatagrid" AutoGenerateColumns="True" HorizontalA ...

  7. C# 值得永久收藏的WPF项目实战(经典)

    01 - 简介 之前也写过好多篇CM框架相关的项目实战文章,比如: C# WPF框架Caliburn.Micro快速搭建 C# WPF框架Caliburn.Micro入门实例1 C# WPF MVVM ...

  8. C# WPF MVVM模式Prism框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Prism提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间通过事 ...

  9. C# WPF MVVM模式Prism框架从零搭建(经典)

    01 - 前言 目前最新的PRISM的版本是8.1.97,本节以6.3.0.0 讲解,可以在Github上获取PRISM的源码. Prism Github地址:https://github.com/P ...

  10. C# WPF MVVM模式Caliburn.Micro框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Caliburn提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间 ...

最新文章

  1. 从零上手 GDB 调试,看这个教程就够了~
  2. c语言输出单链表最大值与最小值,数据结构(C语言版)---顺序表与链表的比较...
  3. php mysql web应用,PHP+MySQL Web应用开发
  4. 人工智能表格票据识别-要素信息自动识别提取
  5. 防爆机器人布里茨还能买到吗_LOL防暴机器人 布里茨皮肤
  6. 用html和js制作一个控制灯泡开关效果
  7. 在win7系统 Keil 开发环境下 Jlink 仿真器连不上解决办法
  8. win2008系统 安装hplaserj1010打印机驱动程序
  9. oracle查询不走索引的一些情况(索引失效)
  10. Paddle2ONNX最新升级:飞桨模型全面支持ONNX协议啦!
  11. CAD看图如何在电脑上快速找到并打开指定CAD图纸
  12. 自用【Python学习记录】——列表、字典
  13. Python的enumerate()函数——浅显易懂
  14. fedora19下修复grub——生命不息,折腾不止
  15. RestfulToolKit:便捷的 IDEA 接口测试神器
  16. 图像识别 - C++读取bmp位图入门
  17. AniGAN: Style-Guided Generative Adversarial Networks for Unsupervised Anime Face Generation
  18. Program type already present: com.google.gson.FieldAttributes
  19. Showdoc升级版本记录
  20. 钉钉小程序上传附件(PDF等非媒体文件)至第三方文件服务器(企业内部应用)

热门文章

  1. python交易是什么意思_py交易什么梗?起源及流行原因
  2. 传奇世界开服教程-地图编号与小地图编号查找方法
  3. 【Java】GUI图形化界面中,setBounds()中参数的含义
  4. Linux_加密和安全详细介绍
  5. sigmoid二分类
  6. 【软件分析/静态程序分析学习笔记】5.数据流分析基础(Data Flow Analysis-Foundations)
  7. Lua的安装配置出现的问题以及解决方案(Win10环境下)
  8. 计算机机水平,湖南省计算机水平等级题型知识点及评分机机制介绍.doc
  9. html5页面缩小 不规整,移动端H5页面的设计尺寸大小规范
  10. Unicdoe【真正的完整码表】对照表(一)