Обновленный заголовок: почему ICommand.CanExecute вызывается все время, а не как событие?
Я принимаю шаблон MVVM в WPF и научился использоватьCommand
, Но в моей реализации делегат, которого я назначил для реализацииCanExecute
всегда называется. Я имею в виду, если я поставлю точку останова внутри функции делегата, это показывает, что эта функция продолжает вызываться. Насколько я понимаю (и это естественно, но я, конечно, могу ошибаться), этого делегата вызывают только тогда, когда я каким-то образом уведомляю об изменении состояния икогдаCommandManager
(пере) проверяетCanExecute
собственности и изменитьIsEnabled
свойство элемента пользовательского интерфейса.
Вот моя реализация VB.NET, которую я получил с версии C #. Я заметил, что мне нужно было внести некоторые изменения в перенесенный код для его компиляции. Может ли это быть в основе 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