I have created a Class which Inherits ICommand
Public Class RelayCommand(Of T)
Implements ICommand
Private ReadOnly m_oExecute As Action(Of T)
Private ReadOnly m_fCanExecute As Predicate(Of T)
Public Sub New(execute As Action(Of T))
Me.New(execute, Nothing)
End Sub
Public Sub New(execute As Action(Of T), canExecute As Predicate(Of T))
If execute Is Nothing Then
Throw New ArgumentNullException("execute")
End If
Me.m_oExecute = execute
Me.m_fCanExecute = canExecute
End Sub
Public Function CanExecute(parameter As T) As Boolean
Return IIf(Me.m_fCanExecute Is Nothing, True, Me.CanExecute(parameter))
End Function
Public Sub Execute(parameter As T)
Me.execute(parameter)
End Sub
Private Function ICommand_CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
Return Me.CanExecute(CType(parameter, T))
End Function
Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
AddHandler(value As EventHandler)
AddHandler CommandManager.RequerySuggested, value
End AddHandler
RemoveHandler(value As EventHandler)
RemoveHandler CommandManager.RequerySuggested, value
End RemoveHandler
RaiseEvent(sender As Object, e As EventArgs)
End RaiseEvent
End Event
Private Sub ICommand_Execute(parameter As Object) Implements ICommand.Execute
Me.Execute(CType(parameter, T))
End Sub
End Class
Public Class RelayCommand
Inherits RelayCommand(Of Object)
Public Sub New(execute As Action(Of Object))
MyBase.New(execute)
End Sub
Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
MyBase.New(execute, canExecute)
End Sub
End Class
In the .xaml file I have wrote this code:
<ComboBox x:Name="cboDatabases" Width="150">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DropDownOpened">
<i:InvokeCommandAction Command="{Binding DataContext.DropDownOpenedCommand,ElementName=cboDatabases}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
And the Command Object in ViewModel
Private m_oDropDownOpenedCommand As RelayCommand
Public ReadOnly Property DropDownOpenedCommand As ICommand
Get
If IsNothing(m_oDropDownOpenedCommand) Then
Me.m_oDropDownOpenedCommand = New RelayCommand(AddressOf Me.DropDownOpened, Function(param) True)
End If
Return Me.m_oDropDownOpenedCommand
End Get
End Property
Private Sub DropDownOpened()
MessageBox.Show("i did it")
End Sub
When I create a new Instance of the Window the code inserts the Property DropDownOpenedCommand
as expected. When I click the combo so as to trigger the event then
the code calls many times this Function in the RelayCommand Class
Public Function CanExecute(parameter As T) As Boolean
Return IIf(Me.m_fCanExecute Is Nothing, True, Me.CanExecute(parameter))
End Function
As a result I get a StackOverflowException
at that Line. The CanExecute
Returns false after the first time that it gets to that line. BUT The parameter
field is always nothing. I think that the parameter
being nothing is a problem but I can't figure how to pass the right argument.
Any Ideas??
I know that I can handle the event in the xaml.vb but I want it as a Command in the Viewmodel.
Public Function CanExecute(parameter As T) As Boolean
Return IIf(Me.m_fCanExecute Is Nothing, True, Me.CanExecute(parameter))
End Function
If Me.m_fCanExecute
is ever not null, the function recurses on itself by evaluating Me.CanExecute()
again. That's where the stackoverflowexception is being generated.
edit:
So the first time you come into this method and Me.m_fCanExecute
is not null, it again executes Me.CanExecute(parameter)
, then Me.m_fCanExecute
is null again, so it calls Me.CanExecute()
, then Me.m_fCanExecute
is null again, so it calls Me.CanExecute()
, then Me.m_fCanExecute
is null again, so it calls Me.CanExecute()
, then Me.m_fCanExecute
is null again, so it calls Me.CanExecute()
, then Me.m_fCanExecute
is null again, so it calls Me.CanExecute()
...
and then you get a StackOverFlowException
. It's an infinite loop.