Winforms 筛选PowerShell中的TreeView节点

Winforms 筛选PowerShell中的TreeView节点,winforms,powershell,treeview,Winforms,Powershell,Treeview,我的树状视图中有大量节点,并且有一个文本框可以过滤这些节点以突出显示匹配的搜索。然而,它有点混乱,因为它显示了所有其他节点,在我更改搜索后,它会使所有节点都展开 我想做点像这样的东西, 但我使用的是Windows窗体/Powershell ISE,似乎很难在自己的代码中实现它 对于关闭节点,我尝试使用(Textbox.textlength-eq 0)这一行来触发关闭所有节点函数,但这不起作用 这是我想要的,它也是这样的。左边是我想要的,右边是我想要的。 下面是我正在使用的搜索函数的一个示例 A

我的树状视图中有大量节点,并且有一个文本框可以过滤这些节点以突出显示匹配的搜索。然而,它有点混乱,因为它显示了所有其他节点,在我更改搜索后,它会使所有节点都展开

我想做点像这样的东西, 但我使用的是Windows窗体/Powershell ISE,似乎很难在自己的代码中实现它

对于关闭节点,我尝试使用(Textbox.textlength-eq 0)这一行来触发关闭所有节点函数,但这不起作用

这是我想要的,它也是这样的。左边是我想要的,右边是我想要的。

下面是我正在使用的搜索函数的一个示例

Add-Type -AssemblyName System.Windows.Forms

function GetNodes([System.Windows.Forms.TreeNodeCollection] $nodes)
{
     foreach ($n in $nodes) {
        $n
        GetNodes($n.Nodes)
     }
}

$form = New-Object System.Windows.Forms.Form
$form.Text ="Test"
$form.Controls.AddRange(@(
    ($txt = [System.Windows.Forms.TextBox] @{
        Location = [System.Drawing.Point]::new(8, 8);
        Width = 100;
    }),
    ($btn = [System.Windows.Forms.Button] @{
        Location = [System.Drawing.Point]::new(120, 8);
        Width = 50;
        Text = "Search";
    }),
    ($tree = [System.Windows.Forms.TreeView] @{
        Location = [System.Drawing.Point]::new(8, 40);
        Width = 170;
        HideSelection = $false
    })
))
$form.AcceptButton= $btn

$tree.Nodes.Add("A1", "A1")
$tree.Nodes.Add("A2", "A2")
$tree.Nodes[0].Nodes.Add("A11", "A11")
$tree.Nodes[0].Nodes.Add("A12", "A12")
$tree.Nodes[1].Nodes.Add("A21", "A21")
$tree.Nodes[1].Nodes.Add("A22", "A22")

$btn.Add_Click({param($sender,$e)
    $nodes = GetNodes($tree.Nodes)
    foreach ($node in $nodes) {
        if($node.Text -like $txt.Text){
            $tree.SelectedNode = $node
            $node.EnsureVisible()
            break
        }
     }
})
$form.ShowDialog() | Out-Null
$form.Dispose()

假设您正在搜索文件夹结构之类的数据源,我将这样做:

  • 创建一个函数,将所有目录的列表递归地放入列表中
  • 创建一个函数来过滤目录列表,并返回目录列表,这些目录的名称中包含特定文本
  • 创建一个函数来填充treeview
  • 创建一个函数来突出显示treenode(如果它包含特定文本)
然后在文本框的文本更改事件中,我将筛选并突出显示树:

代码如下:

Add-Type -AssemblyName System.Windows.Forms

function GetPaths($root)
{
    Get-ChildItem $root -Recurse -Directory | % {
        $_.FullName.Replace($root, "").Trim("\")} 
}

function FilterPaths($paths, $like)
{
    $paths | ? {$_ -like "*$like*"} | % {
        $i = $_.LastIndexOf("$like", [System.Globalization.CompareOptions]::IgnoreCase)
        if($i -gt -1) {
            $j = $_.IndexOf("\", $i, [System.Globalization.CompareOptions]::IgnoreCase)
            if($j -gt -1) {
                $_.SubString(0,$j)
            } else {
                $_
            }
        }
    } 
}

function GetNodes($nodes)
{
     foreach ($n in $nodes) {
        $n
        GetNodes($n.Nodes)
     }
}

function HighlightNodes($nodes, $like)
{
    if(!$like){ return }
    $nodes | ? {$_ -like "*$like*"} | % {
            $_.BackColor = "Yellow"
    }
}

function PopulateTree($treeView, $paths)
{
    $treeView.Nodes.Clear()
    foreach ($path in $paths)
    {
        $lastNode = $null
        $subPathAgg = ""
        foreach ($subPath in ($path -split '\\'))
        {
            $subPathAgg += ($subPath + '\')
            $nodes = $treeView.Nodes.Find($subPathAgg, $true)
            if ($nodes.Length -eq 0) {
                if ($lastNode -eq $null) {
                    $lastNode = $treeView.Nodes.Add($subPathAgg, $subPath)
                } else {
                    $lastNode = $lastNode.Nodes.Add($subPathAgg, $subPath)
                }
            } else {
                $lastNode = $nodes[0]
            }
        }
    }
}

$form = New-Object System.Windows.Forms.Form
$form.Text ="Test"
$form.Controls.AddRange(@(
    ($txt = [System.Windows.Forms.TextBox] @{
        Location = [System.Drawing.Point]::new(8, 8);
        Width = $form.ClientSize.Width - 16;
        Anchor = [System.Windows.Forms.AnchorStyles]13
    }),
    ($tree = [System.Windows.Forms.TreeView] @{
        Location = [System.Drawing.Point]::new(8, 40);
        Width = $form.ClientSize.Width - 16;
        Anchor = [System.Windows.Forms.AnchorStyles]15
        Height = 200;
        HideSelection = $false
    })
))
$form.AcceptButton= $btn
$root = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\ItemTemplates\CSharp"
$paths = GetPaths $root
PopulateTree $tree $paths
$tree.ExpandAll()

$txt.Add_TextChanged({param($sender,$e)
    $tree.BeginUpdate()
    $like = $txt.Text
    $filtered = FilterPaths $paths $like
    PopulateTree $tree $filtered
    HighlightNodes (GetNodes $tree.Nodes) $like
    $tree.ExpandAll()
    $tree.TopNode = $tree.Nodes[0]
    $tree.EndUpdate()
})
$form.ShowDialog() | Out-Null
$form.Dispose()

我缺少的是重新填充这棵树。我试图离开我拥有的数据,而不是改变数据并继续解析它。你是个圣人,非常感谢你。你帮了我这么多。让它搜索节点而不仅仅是路径的任何提示。此工具用于搜索包含安装可执行文件的文件夹,但这些文件夹有一堆小文件夹,这使得加载此文件需要花费很长时间。我的所有节点都在工作和设置,但似乎无法让它搜索$nodes,只有$path。(1)本例从文件系统加载初始数据,但它并不真正关心文件系统。任何可以建模为路径的东西都可以用作数据源,例如IIS中的站点列表等等。(2) 在路径之间搜索肯定比在节点之间搜索快。(3) 在TreeView中无法隐藏节点,所以需要重新创建树。(4) 只需将其保持为
$path |,就可以使
过滤器路径
的运行速度加快一点?{$\ like“*$like*”}
。我添加了GetPaths函数,-Depth 2,这基本上修复了我试图完成的任务,我有一些文件夹需要再深入一层,但对我来说已经足够了。谢谢你的帮助,我将远离搜索节点。酷!没问题:)