0

我创建了一个继承 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当我创建一个新的 Window 实例时,代码会按预期插入。当我单击组合以触发事件时,代码在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 中的命令。

4

2 回答 2

1

除了@Tom Stude 的回答,这个方法也可能会给你带来麻烦:

Public Sub Execute(parameter As T)
    Me.execute(parameter)
End Sub
于 2013-06-18T14:51:50.293 回答
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不为null时,它再次执行Me.CanExecute(parameter),然后Me.m_fCanExecute再次为null,所以它调用Me.CanExecute(),然后Me.m_fCanExecute再次为null,所以它调用Me.CanExecute(),然后Me.m_fCanExecute再次为null,所以它调用Me.CanExecute(),然后Me.m_fCanExecute再次为null,所以它调用Me.CanExecute(),然后Me.m_fCanExecute再次为空,所以它调用Me.CanExecute()...

然后你得到一个StackOverFlowException. 这是一个无限循环。

于 2013-06-17T19:45:23.130 回答