Фильтровать узлы TreeView в PowerShell - PullRequest
1 голос
/ 29 января 2020

У меня есть тонна узлов в TreeView, и у меня есть текстовое поле, которое фильтрует их, чтобы выделить соответствующий поиск. Тем не менее, он немного запутан, поскольку показывает все другие узлы, и после того, как я изменил свой поиск, он оставляет все узлы развернутыми.

Я пытаюсь сделать что-то вроде этого, https://www.codeproject.com/Tips/1000621/Filtering-and-Hiding-Tree-Nodes-WinForms Но я использую Windows формы / Powershell ISE и, похоже, изо всех сил пытаюсь внедрить его в свой собственный код.

Для закрытия узлов я пытался использовать вещи вдоль линии (Textbox.textlength -eq 0), чтобы вызвать функцию закрытия всех узлов, но это не сработало.

Вот то, что я хочу, чтобы это тоже выглядело. Левый - это то, что я хочу, Правый - это то, на что похожа моя. enter image description here

Вот пример функции поиска, которую я использую.

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

1 Ответ

1 голос
/ 01 февраля 2020

Предполагая, что вы ищете источник данных, например структуру папок, я сделаю следующее:

  • Создайте функцию для рекурсивного получения списка всех каталогов в список
  • Создайте функцию, чтобы отфильтровать список каталогов и вернуть список каталогов, которые содержат c текст в своих именах.
  • Создайте функцию для заполнения древовидной структуры
  • Создайте функцию чтобы выделить триод, если он содержит специфицированный c текст

Затем в событии с измененным текстом текстового поля я отфильтрую и выделю дерево:

enter image description here

Вот код:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...