Título actualizado: ¿Por qué se llama a ICommand.CanExecute todo el tiempo, en lugar de funcionar como un evento?

Estoy adoptando el patrón MVVM en WPF y he aprendido el uso deCommand. Pero en mi implementación, el delegado que asigné para implementarCanExecute Siempre se llama. Quiero decir que si pongo un punto de interrupción dentro de la función de delegado, muestra que esta función sigue siendo llamada. A mi entender (y una forma natural de pensar, pero por supuesto que puedo estar equivocado), este delegado solo es llamado cuando de alguna manera notifico el cambio de estado y ahí es cuandoCommandManager (re) comprueba elCanExecute propiedad y modificar elIsEnabled Propiedad del elemento UI.

Aquí está mi implementación de VB.NET, que obtuve originalmente de una versión de C #. Noté que necesitaba hacer algún cambio en el código portado para que se compile. ¿Podría ser el subyacente de C # y VB.NET es diferente? Entonces, ¿alguien puede proporcionarme una implementación VB.NET original, o señalarme qué es lo que está mal o hacer si entiendo correctamente el comportamiento del Comando?

Aquí está mi versión de 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

Y cómo instanciar un objeto es algo como esto:

MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)

donde CanExecuteExec, por supuesto, tiene la firma como esta:

Private Function CanExecuteExec(obj As Object) As Boolean

Como he mencionado, elCanExecuteExec es llamado todo el tiempo. Supongo que es ineficiente, imagina que tengo cientos deCommand objetos y la mayoría de losCanExecute De ellos no se cambian la mayor parte del tiempo.

ACTUALIZAR:

Alguien diceCanExecute De hecho, es llamado todo el tiempo, mientras que otros dicen lo contrario. No soy un experto en esto, pero debo decir que la segunda opinión suena más natural y tiene más sentido para mí. Aunque todavía tengo que averiguar si eso es cierto, ¿por qué WPF detecta el cambio todo el tiempo para que siga revisando elCanExecute

Respuestas a la pregunta(3)

Su respuesta a la pregunta