这个问题在这里已有答案:
想象一下,你有一个简单的WPF窗口,上面只有一个TextBox
和一个Button
。 TextBox
的Text
财产被绑定到一个名为FileName
的财产,而Button
的Command
财产被绑定到一个名为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
TextBox
和Button
之间没有明显的联系,FileName
属性和ImportCommand
之间没有明显的联系。
那么,ImportCommand
如何检测,我可能已经改变了FileName
属性,并且这种变化可能会影响Button
的启用状态,ImportCommand
必然会?
WPF是否会在任何CanExecute
和任何正在发生的Command
上调用PropertyChanged
?对我来说听起来像很多不必要的工作?
来自RelayCommad的CanExecuteChanged事件侦听由CommandManager.InvalidateRequerySuggested方法引发的CommandManager.RequerySuggested事件。
CommandManager再次侦听InputManager KeyUp MouseUp或GotKeyboardFocus或LostKeyboardFocus事件,并调用InvalidateRequerySuggested以通知UI调用Command的CanExecute方法。