我在 WPF 中采用 MVVM 模式,并且已经学会了Command
. 但是在我的实现中,我分配给实现的委托CanExecute
总是被调用。我的意思是,如果我在委托函数中放置一个断点,则表明该函数不断被调用。CommandManager
据我了解(也是一种自然的思维方式,但当然我可能是错的),只有当我以某种方式通知状态更改并且(重新)检查CanExecute
属性并修改IsEnabled
属性时,才会调用此委托用户界面元素。
这是我最初从 C# 版本获得的 VB.NET 实现。我确实注意到我需要对移植的代码进行一些更改才能编译它。会不会是 C# 和 VB.NET 的底层不同?那么有人可以为我提供一个原始的 VB.NET 实现,或者如果我正确理解了 Command 行为,可以指出什么是错误的或做什么?
这是我的 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
大部分时间都没有改变。
更新:
有人说CanExecute
确实总是被调用,而另一些人则相反。我不是这方面的专家,但我不得不说第二种意见听起来更自然,对我来说更有意义。虽然我仍然需要弄清楚这是否属实,但为什么 WPF 一直检测到更改,以便它不断检查CanExecute