我创建了一个继承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
在.xaml文件中我写了这段代码:
<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>
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
当我创建窗口的新实例时,代码会按预期插入Property DropDownOpenedCommand
。当我单击组合以便触发事件时
代码在RelayCommand Class
Public Function CanExecute(parameter As T) As Boolean
Return IIf(Me.m_fCanExecute Is Nothing, True, Me.CanExecute(parameter))
End Function
结果我在那条线上得到StackOverflowException
。 CanExecute
第一次到达该行后返回false。 但是 parameter
字段始终没有。我认为parameter
不存在是一个问题,但我无法想象如何传递正确的论点。
有任何想法吗??
我知道我可以在xaml.vb中处理事件,但我希望它在Viewmodel中作为命令。
答案 0 :(得分:1)
除了@Tom Studee的答案之外,这种方法也可能会给你带来麻烦:
Public Sub Execute(parameter As T)
Me.execute(parameter)
End Sub
答案 1 :(得分:0)
Public Function CanExecute(parameter As T) As Boolean
Return IIf(Me.m_fCanExecute Is Nothing, True, Me.CanExecute(parameter))
End Function
如果Me.m_fCanExecute
永远不为空,则该函数会通过再次评估Me.CanExecute()
来自行处理。这就是生成stackoverflowexception的地方。
编辑:
因此,当您第一次使用此方法并且Me.m_fCanExecute
不为空时,它会再次执行Me.CanExecute(parameter)
,然后Me.m_fCanExecute
再次为空,因此它会调用Me.CanExecute()
,然后Me.m_fCanExecute
再次为空,因此它调用Me.CanExecute()
,然后Me.m_fCanExecute
再次为空,因此它调用Me.CanExecute()
,然后Me.m_fCanExecute
再次为空,所以它调用Me.CanExecute()
,然后Me.m_fCanExecute
再次为空,因此调用Me.CanExecute()
...
然后你得到StackOverFlowException
。这是一个无限循环。