Commands 究竟是如何得到通知来执行它们的 CanExecute 的?

How exactly do Commands get notified to execute their CanExecute?

想象一下,您有一个简单的 WPF window,上面只有一个 TextBox 和一个 ButtonTextBoxText 属性 绑定到名为 FileName 的 属性 和 ButtonCommand 属性 绑定到名为 ImportCommand.

的 属性
<StackPanel>
    <TextBox Text="{Binding FileName, UpdateSourceTrigger=PropertyChanged}" />
    <Button Content="Import" Command="{Binding ImportCommand}" />
</StackPanel>

视图模型也是相当多的样板代码。

Public Class MainViewModel
    Inherits ObservableItem

    Private _fileName As String
    Private _importCommand As ICommand = New RelayCommand(AddressOf Me.Import, AddressOf Me.CanImport)

    Public Sub New()
        Me.FileName = "C:\Temp\temp.dat"
    End Sub

    Public Property FileName As String
        Get
            Return _fileName
        End Get
        Set(value As String)
            MyBase.SetProperty(Of String)(_fileName, value)
        End Set
    End Property

    Public ReadOnly Property ImportCommand As ICommand
        Get
            Return _importCommand
        End Get
    End Property

    Private Sub Import()
        Throw New NotImplementedException
    End Sub

    Private Function CanImport() As Boolean
        Return Not String.IsNullOrEmpty(Me.FileName) AndAlso IO.File.Exists(Me.FileName)
    End Function

End Class

TextBoxButton之间没有明显的联系,FileName属性和ImportCommand之间没有明显的联系。

那么,ImportCommand 如何检测到我可能更改了 FileName 属性 并且此更改可能会影响 Button 的启用状态, ImportCommand 绑定到?

WPF 是否在 any Commandany PropertyChanged 上调用 CanExecute?对我来说听起来像是很多不必要的工作?

RelayCommad 的 CanExecuteChanged 事件侦听 CommandManager.InvalidateRequerySuggested 方法引发的 CommandManager.RequerySuggested 事件。

CommandManager再次监听InputManager KeyUp MouseUp或GotKeyboardFocus或LostKeyboardFocus事件,调用InvalidateRequerySuggested通知UI调用Command的CanExecute方法