Aktualisierter Titel: Warum wird ICommand.CanExecute die ganze Zeit aufgerufen, anstatt wie ein Ereignis zu arbeiten?
Ich übernehme MVVM-Muster in WPF und habe die Verwendung von gelerntCommand
. Aber in meiner Implementierung der Delegat, den ich mit der Implementierung beauftragt habeCanExecute
heißt immer. Ich meine, wenn ich einen Haltepunkt in die Delegate-Funktion setze, zeigt dies, dass diese Funktion immer wieder aufgerufen wird. Nach meinem Verständnis (und einer natürlichen Denkweise, aber natürlich kann ich mich irren) wird dieser Delegierte nur dann gerufen, wenn ich die Änderung des Zustands irgendwie mitteilte und dannCommandManager
(erneut) prüft dieCanExecute
Eigentum und ändern Sie dieIsEnabled
Eigenschaft des UI-Elements.
Hier ist meine Implementierung von VB.NET, die ich ursprünglich aus einer C # -Version erhalten habe. Mir ist aufgefallen, dass ich einige Änderungen am portierten Code vornehmen musste, damit er kompiliert werden konnte. Könnte es sein, dass die Basis von C # und VB.NET anders ist? Kann mir jemand eine originale VB.NET-Implementierung zur Verfügung stellen oder mich darauf hinweisen, was falsch ist oder was tun, wenn ich das Befehlsverhalten richtig verstehe?
Hier ist meine VB.NET-Version:
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
Und wie ich ein Objekt instanziiere, ist ungefähr so:
MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)
Wobei die CanExecuteExec natürlich die Signatur wie folgt hat:
Private Function CanExecuteExec(obj As Object) As Boolean
Wie ich schon sagte, dieCanExecuteExec
wird die ganze Zeit angerufen. Ich denke, es ist ineffizient. Stellen Sie sich vor, ich habe Hunderte vonCommand
Objekte und die meistenCanExecute
von ihnen werden die meiste Zeit nicht verändert.
Jemand sagt dasCanExecute
in der Tat wird die ganze Zeit angerufen, während andere das Gegenteil sagen. Ich bin kein Experte in diesem Bereich, aber ich muss sagen, dass die zweite Meinung natürlicher klingt und für mich sinnvoller ist. Obwohl ich immer noch herausfinden muss, ob das zutrifft, erkennt WPF die Änderung die ganze Zeit, damit es das überprüftCanExecute