WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因
原文:WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因
在 WPF 中,你可以使用 Command="{Binding WalterlvCommand}" 的方式来让 XAML 中的一个按钮或其他控件绑定一个命令。这样,按钮的可用性会自动根据 WalterlvCommand 当前 CanExecute 的状态来改变。这本是一个非常智能的特性,直到你可能发现你按钮的可用性状态不正确……
本文介绍默认情况下,WPF 在 UI 上的这些命令会在什么时机进行刷新;以及没有及时刷新时,可以如何强制让这些命令的可用性状态进行刷新。了解了这些,你可能能够解决你在 WPF 程序中命令绑定的一些坑。
This post is written in multiple languages. Please select yours:
- WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因 - walterlv
- When WPF Commands update their CanExecute states? - walterlv
一个最简单的例子
<Button x:Name="TestCommand" Command="{Binding WalterlvCommand}" />
- 1
public class Walterlv
{
// 省略了此命令的初始化。
public WalterlvCommand WalterlvCommand { get; }
}
public class WalterlvCommand : ICommand
{
public bool SomeFlag { get; set; }
bool ICommand.CanExecute(object parameter)
{
// 判断命令的可用性。
return SomeFlag;
}
void ICommand.Execute(object parameter)
{
// 省略了执行命令的代码。
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
假如 SomeFlag 一开始是 false,5 秒种后变为 true,那么你会注意到这时的按钮状态并不会刷新。
var walterlv = new Walterlv();
TestCommand.DataContext = walterlv;
await Task.Delay(5000);
walterlv.WalterlvCommand.SomeFlag = true;
- 1
- 2
- 3
- 4
- 5
当然,以上所有代码会更像伪代码,如果你不熟悉 WPF,是一定编译不过的。我只是在表达这个意思。
如何手动刷新命令
调用以下代码,即可让 WPF 中的命令刷新其可用性:
CommandManager.InvalidateRequerySuggested();
- 1
WPF 的命令在何时刷新?
默认情况下,WPF 的命令只会在以下时机刷新可用性:
KeyUpMouseUpGotKeyboardFocusLostKeyboardFocus
使用通俗的话来说,就是:
- 键盘按下的按键抬起的时候
- 在鼠标的左键或者右键松开的时候
- 在任何一个控件获得键盘焦点或者失去键盘焦点的时候
这部分的代码可以在这里查看:
最关键的代码贴在这里:
// 省略前面。
if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent ||
e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent ||
e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
{
CommandManager.InvalidateRequerySuggested();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
然而,并不是只在这些时机进行刷新,还有其他的时机,比如这些:
- 在
Menu菜单的子菜单项打开的时候(参见 MenuItem.OnIsSubmenuOpenChanged) - 在长按滚动条中的按钮以连续滚动的过程中(参见 Tracker.DecreaseRepeatButton)
- 在
DataGridCell的只读属性改变的时候(参见 DataGridCell.OnNotifyIsReadOnlyChanged) - 在
DataGrid中的各种各样的操作中(参见 DataGrid) - 在
JournalNavigationScope向后导航的时候(参见 JournalNavigationScope.OnBackForwardStateChange) - 还有其他,你可以在此链接双击
InvalidateRequerySuggested查看:InvalidateRequerySuggested
我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。
如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因的更多相关文章
- 浏览器自动刷新——基于Nodejs的Gulp LiveReload与VisualStudio完美结合。
本文版权桂博客园和作者吴双共同所有,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/6016055.html 写在前面 大家好我是博客园的蜗牛,博客园的蜗牛就是我 ...
- Sublime3和Chrome配置自动刷新网页【实测可用】
SublimeText2下的LiveReload在SublimeText3下无法正常使用,本文整理SublimeText3安装LiveReload的方法.win7下实测可用! 安装成功后,就不需要再手 ...
- gulp之压缩合并MD5清空替换加前缀以及自动编译自动刷新浏览器大全
gulp是基于流的前端构件化工具.目前比较火的前端构建化工具还是挺多的,grunt gulp fis3等等. 这个鬼东西有什么用?请参考https://www.zhihu.com/question/3 ...
- SQL实现类似于自动刷新数据的功能
有时需要在SQL中,定时刷新某张表,比如说是要定时查询某张表的行数,通常做法就是手动的按F5去执行来刷新数据.但是如果这个定时查询历时较长,10分钟,或半小时,手动的话肯定是要崩溃了.貌似SQL没有像 ...
- Windows Phone 8 LongListSelector实现下拉自动刷新列表
LongListSelector是一个加强版的列表控件,它可以实现分组的列表,如系统人脉列表的交互效果就可以利用LongListSelector控件去实现,同时LongListSelector也一样可 ...
- gulp自动刷新插件
gulp自动刷新的插件很多,但是感觉最好用的还是 browser-sync 插件.如果不想用命令行,也可以使用 browser-sync界面工具 先安装 browser-sync 插件: npm in ...
- BrowserSync,调试利器--自动刷新(转
---恢复内容开始--- 请想象这样一个场面:你开着两个显示器,一边是IDE里的代码,另一边是浏览器里的你正在开发的应用.此时桌上还放着你的手机,手机里也是这个开发中的应用.然后,你新写了一小段代码, ...
- gulp+browserSync+nodemon 实现express 全端自动刷新的实践
学习过程宝宝心里苦,不能怨政府.. 兴趣所致,一直放不下nodejs的学习,时隔多日,又把express捡起来打算重新再学学,一直没什么太大的长进,和实际的项目经验.真的醉了,太懒了. 今天在重新研究 ...
- gulp最佳实践(包含js,css,html预编译,合并,压缩,浏览器自动刷新)
gulp是基于流的自动化构建工具官方网址:http://www.gulpjs.com.cn/ 一.安装需要的模块 1.新建package.json,输入下面的内容 { "name" ...
随机推荐
- Mean Average Precision(mAP),Precision,Recall,Accuracy,F1_score,PR曲线、ROC曲线,AUC值,决定系数R^2 的含义与计算
背景 之前在研究Object Detection的时候,只是知道Precision这个指标,但是mAP(mean Average Precision)具体是如何计算的,暂时还不知道.最近做OD的任 ...
- 分享一个Python脚本--统计redis key类型数据大小分布
概述 今天主要介绍怎么统计redis key类型数据大小分布. 原理:使用redis命令: scan.pipline.type 和 debug object 来得到 redis key 信息. 脚本 ...
- INDY10 BASE64编码
INDY10 BASE64编码 DELPHI自带的BASE64单元,在项目中使用发现非常没有效率,INDY10的好用. uses IdCoderMIME BASE64编码类:TIdEncoderMIM ...
- uniapp - emmet
话说,emment是官方uniapp直接引入的.基本上没做啥修改:可以点这里查看所有用法 - http://emmet.evget.com/ 1.类似css层级写法 1.1 view.ok>vi ...
- SpringBoot(十七):SpringBoot2.1.1数据类型转化器Converter
什么场景下需要使用类型化器Converter? springboot2.1.1在做Restful Api开发过程中往往希望接口直接接收date类型参数,但是默认不加设置是不支持的,会抛出异常:系统是希 ...
- C#中得到每周,每月,每季,每年的年初末日期
DateTime表示时间上的一刻,通常以日期和当天的时间表示.借用这个结构,我们可以实现较丰富的功能,本文给出得到每周每天的方法,及得到本月第一天,本月最后一天,本季第一天,本季最后一天,本年第一天及 ...
- log配置文件log4j.propeties(配置保存日志文件的相对路径)
log配置文件log4j.propeties(配置保存日志文件的相对路径) log4j.propeties文件: #日志的4种级别ERROR(错误).WARN(警告潜在的错误).INFO(粗粒度信息) ...
- Anaconda用conda创建python虚拟环境
Anaconda用conda创建python虚拟环境 一.简介 conda可以理解为一个工具,也是一个可执行命令,其核心功能是包管理与环境管理.包管理与pip的使用类似,环境管理则允许用户方便地安装不 ...
- mysql group by 查询非聚集列
本文为博主原创,转载请注明出处: mysql使用group by可以使用一些聚合函数,可以计算最大值(max(column)),最小值(min(column)),总和(sum(column)),平均数 ...
- python初级(302) 6 对象(一)
作业: 1.编写一个Dog类,并生成对象dog,属性包含颜色,大小,重量,可以汪汪叫,摇尾巴,跑 # -*- coding: utf-8 -*- class Dog: def __init__(sel ...
