执行命令时StackOverflowExcpetion

时间:2013-06-17 19:39:31

标签: wpf vb.net mvvm .net-4.5 stack-overflow

我创建了一个继承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

结果我在那条线上得到StackOverflowExceptionCanExecute第一次到达该行后返回false。 但是 parameter字段始终没有。我认为parameter不存在是一个问题,但我无法想象如何传递正确的论点。 有任何想法吗?? 我知道我可以在xaml.vb中处理事件,但我希望它在Viewmodel中作为命令。

2 个答案:

答案 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。这是一个无限循环。