Zaktualizowany tytuł: Dlaczego ICommand.CanExecute jest wywoływany przez cały czas, zamiast pracować jak wydarzenie?

Przyjmuję wzór MVVM w WPF i nauczyłem się korzystać zCommand. Ale w mojej realizacji delegat, którego wyznaczyłem do wdrożeniaCanExecute jest zawsze nazywany. To znaczy, jeśli umieściłem punkt przerwania wewnątrz funkcji delegata, to pokazuje, że ta funkcja nadal jest wywoływana. Dla mojego zrozumienia (i naturalny sposób myślenia, ale oczywiście mogę się mylić), ten delegat zostaje wezwany tylko wtedy, gdy jakoś powiadamiam o zmianie stanu i wtedyCommandManager (re) sprawdzaCanExecute własność i zmodyfikujIsEnabled właściwość elementu interfejsu użytkownika.

Oto moja implementacja VB.NET, którą otrzymałem pierwotnie z wersji C #. Zauważyłem, że muszę dokonać pewnych zmian w przeniesionym kodzie, aby mógł się skompilować. Czy może to być podstawa C # i VB.NET jest inny? Czy ktoś może mi udostępnić oryginalną implementację VB.NET lub wskazać, co jest nie tak lub co zrobić, jeśli poprawnie rozumiem zachowanie polecenia?

Oto moja wersja 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

A jak tworzę instancję obiektu, to coś takiego:

MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)

gdzie CanExecuteExec ma oczywiście taki podpis:

Private Function CanExecuteExec(obj As Object) As Boolean

Jak wspomniałem,CanExecuteExec ciągle się nazywa. Sądzę, że to nieefektywne, wyobraź sobie, że mam setkiCommand przedmioty i większośćCanExecute z nich nie zmienia się przez większość czasu.

AKTUALIZACJA:

Ktoś mówiCanExecute rzeczywiście jest wywoływany przez cały czas, podczas gdy inni mówią przeciwnie. Nie jestem ekspertem w tej dziedzinie, ale muszę powiedzieć, że druga opinia brzmi bardziej naturalnie i ma dla mnie więcej sensu. Chociaż nadal muszę się dowiedzieć, czy to prawda, dlaczego WPF cały czas wykrywa zmianę, aby nadal sprawdzaćCanExecute

questionAnswers(3)

yourAnswerToTheQuestion