When WPF Commands update their CanExecute states?

2023-10-22 09:43:18 浏览数 (2)

When writing Command="{Binding WalterlvCommand}" into your XAML code and your button or other controls can automatically execute command and updating the command states, such as enabling or disabling the button.

We’ll talk about when the UI commands will refresh their can-execute states and how to force updating the states.

This post is written in multiple languages. Please select yours:

中文 English

This post is written for my Stack Overflow answer:

  • Why C# WPF button binding command won’t change view after using simple injector? - Stack Overflow

A simple sample

1

<Button x:Name="TestCommand" Command="{Binding WalterlvCommand}" />

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

public class Walterlv { // Assume that I've initialized this command. public WalterlvCommand WalterlvCommand { get; } } public class WalterlvCommand : ICommand { public bool SomeFlag { get; set; } bool ICommand.CanExecute(object parameter) { // Return the real can execution state. return SomeFlag; } void ICommand.Execute(object parameter) { // The actual executing procedure. } }

See this code below. After 5 seconds, the button will still be disabled even that we set the SomeFlat to true.

1 2 3 4 5

var walterlv = new Walterlv(); TestCommand.DataContext = walterlv; await Task.Delay(5000); walterlv.WalterlvCommand.SomeFlag = true;

How to update manually?

Call this method after you want to update your command states if it won’t update:

1

CommandManager.InvalidateRequerySuggested();

When do the commands update their states?

Commands only update when these general events happen:

  • KeyUp
  • MouseUp
  • GotKeyboardFocus
  • LostKeyboardFocus

You can see the code here:

  • CommandDevice.PostProcessInput

And the key code is here:

1 2 3 4 5 6 7

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(); }

Actually, not only those events above but also these methods below refresh the command states:

  • When opening a submenu of a MenuItem. See MenuItem.OnIsSubmenuOpenChanged
  • When pressing and holding a RepeatButton in a Tracker. Tracker.DecreaseRepeatButton
  • When change the readonly property of DataGridCell. DataGridCell.OnNotifyIsReadOnlyChanged
  • When doing many operations in a DataGrid. DataGrid
  • When navigating back in a JournalNavigationScope. JournalNavigationScope.OnBackForwardStateChange
  • And others, you can find references of InvalidateRequerySuggested: InvalidateRequerySuggested

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/when-wpf-commands-update-their-states-en.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected]) 。

0 人点赞