I accept the MVVM pattern in WPF and learned about using Command . But in my implementation, the delegate assigned to the CanExecute implementation is always called. I mean, if I set a breakpoint inside the delegate function, this shows that this function continues to receive calls. In my understanding (and natural thinking, but of course I can be wrong), this delegate is called only when I somehow notify about a state change and that when CommandManager (re) checks the CanExecute property and change the IsEnabled property of the interface element.
Here is my VB.NET implementation that I got from the C # version. I noticed that I need to make some changes to the ported code so that it can compile. Could the basis of C # and VB.NET be different? So can someone provide me with the original implementation of VB.NET or tell me what is wrong, or if I understand the behavior of the command correctly?
Here is my version of 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
And as I instantiate the object, it is something like this:
MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)
where CanExecuteExec, of course, has this signature:
Private Function CanExecuteExec(obj As Object) As Boolean
As I mentioned, calling CanExecuteExec calls all the time. I think this is inefficient, imagine that I have hundreds of Command objects, and most of them CanExecute no longer change.
UPDATE:
Someone says that CanExecute really CanExecute called all the time, while others say the opposite. I am not an expert in this, but I must say that the second opinion sounds more natural and makes more sense to me. Although I still need to find out if this is true, why WPF constantly detects a change so that it continues to validate CanExecute