首页 > 解决方案 > 在 PowerShell 中过滤 TreeView 节点

问题描述

我的 TreeView 中有大量节点,并且有一个文本框可以过滤它们以突出显示匹配的搜索。但是,它显示所有其他节点有点混乱,并且在我更改搜索后,它会使所有节点都展开。

我正在尝试做这样的事情,https://www.codeproject.com/Tips/1000621/Filtering-and-Hiding-Tree-Nodes-WinForms 但我使用的是 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()

标签: winformspowershelltreeview

解决方案


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

  • 创建一个函数以递归方式获取所有目录的列表到列表中
  • 创建一个函数来过滤目录列表并返回名称中包含特定文本的目录列表。
  • 创建一个函数来填充树视图
  • 如果它包含特定文本,则创建一个函数以突出显示树节点

然后在文本框的文本更改事件中,我将过滤并突出显示树:

在此处输入图像描述

这是代码:

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()

推荐阅读