TreeView对象的SelectedNode属性挂起表单多线程

时间:2016-02-08 18:56:58

标签: multithreading winforms powershell treeview

我正在处理GUI脚本,我遇到了TreeView对象的问题。当我尝试显示SelectedNode属性或尝试使用另一个线程中显示的TreeView的GetNodeAt()方法时,会发生此问题。我可以自己显示TreeView对象。这是我尝试做的一个示例:

    $form = new-object system.windows.forms.form
    $treeview = new-object system.windows.forms.treeview
    $treeview.name = "tree view"
    $treeview.add_afterselect({write-host $this.selectednode})
    $treenode = new-object system.windows.forms.treenode
    $treenode.name = "tree node"
    $treenode.text = "tree node"
    $treenode2 = new-object system.windows.forms.treenode
    $treenode2.name = "second tree node"
    $treenode2.text = "second tree node"
    $treeview.nodes.addrange(@($treenode,$treenode2))
    $form.controls.add($treeview)
    $thread = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
    $thread.Open()
    $thread.SessionStateProxy.SetVariable("form",$form)
    $thepipe = $thread.CreatePipeline({$form.Showdialog()})
    $thepipe.Input.Close()
    $thepipe.InvokeAsync()

问题来自行$treeview.add_afterselect({write-host $this.selectednode})当我单击树视图中的节点时,表单将挂起,我必须终止Powershell进程。奇怪的是我可以毫无问题地显示TreeView对象。像这样:$treeview.add_afterselect({write-host $this})。这将返回TreeView对象没有问题。我也尝试使用它$treeview.add_nodemouseclick({write-host $this.getnodeat($_.x,$_.y)})。这也将挂起表格。

问题来自于另一个线程中显示的表单,因为当我执行相同的代码但将表单保留在同一个线程中时,我没有显示所选节点的问题。像这样:

    $form = new-object system.windows.forms.form
    $treeview = new-object system.windows.forms.treeview
    $treeview.name = "tree view"
    $treeview.add_afterselect({write-host $this.selectednode})
    $treenode = new-object system.windows.forms.treenode
    $treenode.name = "tree node"
    $treenode.text = "tree node"
    $treenode2 = new-object system.windows.forms.treenode
    $treenode2.name = "second tree node"
    $treenode2.text = "second tree node"
    $treeview.nodes.addrange(@($treenode,$treenode2))
    $form.controls.add($treeview)
    $form.Showdialog()

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

如果您查看TreeViewEventHandler方法签名,您会发现它需要两个参数,senderTreeViewEventArgs对象。

您可以通过声明自己的命名参数来“拦截”这些参数,如下所示:

$treeview.add_AfterSelect({
    param($s,$e)

    # $e now refers to the TreeViewEventArgs
    Write-Host $e.Node
})

或者您可以依赖自动事件变量$Sender$EventArgs

$treeview.add_AfterSelect({
    Write-Host $EventArgs.Node
})

您可能需要查看Register-ObjectEventabout_Automatic_Variables

的帮助文件

不要在事件操作中使用$this - 它应该在脚本方法定义中用作实例引用,如下所示:

PS C:\> $obj = New-Object psobject -Property @{ Number = 3 }
PS C:\> $obj |Add-Member -Type ScriptMethod -Name GetSquare -Value { return $this.Number * $this.Number }
PS C:\> $obj.GetSquare()
9
PS C:\> $obj.Number = 4
PS C:\> $obj.GetSquare()
16