我在 WPF 中采用 MVVM 模式并学习了使用Command
。但在我的实现中,我分配来实现的代表CanExecute
总是被调用。我的意思是,如果我在委托函数内放置一个断点,它表明该函数不断被调用。根据我的理解(也是一种自然的思维方式,但我当然可能是错的),只有当我以某种方式通知状态发生变化时,才会调用该代表,而此时CommandManager
(重新)检查CanExecute
属性并修改IsEnabled
UI 元素的属性。
这是我的 VB.NET 实现,它最初是从 C# 版本获得的。我确实注意到我需要对移植的代码进行一些更改才能编译。难道是C#和VB.NET的底层不同?那么有人可以为我提供一个原始的 VB.NET 实现,或者指出我哪里出了问题,或者如果我正确理解了命令行为该怎么办?
这是我的 VB.NET 版本:
Public Class CommandBase
Implements ICommand
Public Property ExecuteDelegate() As Action(Of Object)
Public Property CanExecuteDelegate() As Predicate(Of Object)
Public Sub New()
End Sub
Public Sub New(execute As Action(Of Object))
Me.New(execute, Nothing)
End Sub
Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
If execute Is Nothing Then
Throw New ArgumentNullException("execute")
End If
ExecuteDelegate = execute
CanExecuteDelegate = canExecute
End Sub
Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
Return If(CanExecuteDelegate Is Nothing, True, CanExecuteDelegate(parameter))
End Function
Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
AddHandler(ByVal value As EventHandler)
If CanExecuteDelegate IsNot Nothing Then
AddHandler CommandManager.RequerySuggested, value
End If
End AddHandler
RemoveHandler(ByVal value As EventHandler)
If CanExecuteDelegate IsNot Nothing Then
RemoveHandler CommandManager.RequerySuggested, value
End If
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
CommandManager.InvalidateRequerySuggested()
End RaiseEvent
End Event
Public Sub Execute(parameter As Object) Implements ICommand.Execute
If ExecuteDelegate IsNot Nothing Then ExecuteDelegate.Invoke(parameter)
End Sub
Public Sub RaiseCanExecuteChanged()
CommandManager.InvalidateRequerySuggested()
End Sub
End Class
我如何实例化一个对象是这样的:
MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)
其中 CanExecuteExec 当然具有如下签名:
Private Function CanExecuteExec(obj As Object) As Boolean
正如我提到的,CanExecuteExec
一直被打电话。我想这效率很低,想象一下我有数百个Command
对象和大多数CanExecute
其中大部分时间都不会改变。
UPDATE:
有人说CanExecute
确实总是被叫,而其他人却说相反。我不是这方面的专家,但我不得不说第二种意见听起来更自然,对我来说更有意义。虽然我仍然需要弄清楚这是否属实,但为什么 WPF 始终检测到更改,以便它不断检查CanExecute