PowerShell .NET如果选择了所有子节点,则仅检索父节点

时间:2015-01-14 07:38:06

标签: .net winforms forms powershell

我想知道如何在选择所有子节点时检索父节点的名称。在下面的代码中,函数Get-CheckedNodes检索前面带有复选标记的所有内容。

在下面的示例中,如果您选择'Cars>蓝色'它将回归:兰博基尼,玛莎拉蒂和蓝色。这是正确的,但我只想让它报告父'Blue',因为一切都被选中了。但是,当只有一辆车被选中时,它应该只报告那辆车,而不是它的父母。

代码:

Function Add-Node($Nodes, $Path) {  
    $Path.Split("/") | % {
        Write-Verbose "Searching For: $_"
        $SearchResult = $Nodes.Find($_, $False)

    If ($SearchResult.Count -eq 1) {
      Write-Verbose "Selecting: $($SearchResult.Name)"
      $Nodes = $SearchResult[0].Nodes
    }
    Else {
      Write-Verbose "Adding: $_"
      $Node = New-Object Windows.Forms.TreeNode($_)
      $Node.Name = $_
      $Nodes.Add($Node)  | Out-Null
    }
  }
}

Function Get-CheckedNodes($nodes) {
    foreach ($n in $Nodes) {
        if ($n.nodes.count -gt 0) {
            Get-CheckedNodes $n.nodes
        }
        if ($n.checked) {
            Write-Output $n.Name
        }           
    }   
}

Function Select-ChildNodes($node) {
    $checkStatus = $node.Checked
    foreach ($n in $node.Nodes) {
        $n.checked = $checkstatus
        Select-ChildNodes($n)
    }
}

Function Select-ParentNode($node) {
    $parent = $node.Parent
    if($parent -eq $null) {
        return
    }
    $parent.checked = $true
    foreach ($n in $parent.Nodes) {
        if(!$n.checked) {
            $parent.Checked = $false
            break
        }  
    }
    Select-ParentNode($parent)
}

$script:SelectedOU = $null

Add-Type -AssemblyName System.Windows.Forms
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = '342, 502'
$Form.FormBorderStyle = 'FixedDialog'

$ButtonOK_Click = {
    if ($script:SelectedOU = Get-CheckedNodes $treeView.Nodes) {
        $Form.close()
    }
    elseif (([System.Windows.Forms.MessageBox]::Show(
                "You haven't selected anything.`nAre you sure you want to leave?", 
                "Oops!",'YesNo','Information')) -eq 'Yes') {$Form.close()}
}

$Treeview_AfterCheck = {
    $Treeview.Remove_AfterCheck($Treeview_AfterCheck)
    Select-ChildNodes($_.node)
    Select-ParentNode($_.node)
    $Treeview.Add_AfterCheck($Treeview_AfterCheck)
}

$TreeView = New-Object System.Windows.Forms.TreeView
$TreeView.Dock = 'Fill'
$TreeView.CheckBoxes = $true
$Treeview.Add_AfterCheck($Treeview_AfterCheck)

Add-Node $TreeView.Nodes "Fruits"  
Add-Node $TreeView.Nodes "Vegetables"  
Add-Node $TreeView.Nodes "Cars" 
Add-Node $TreeView.Nodes "Cars/Blue" 
Add-Node $TreeView.Nodes "Cars/Blue/Lamborghini"
Add-Node $TreeView.Nodes "Cars/Blue/Maserati"
Add-Node $TreeView.Nodes "Cars/Red" 
Add-Node $TreeView.Nodes "Cars/Red/Lamborghini"
Add-Node $TreeView.Nodes "Cars/Red/Maserati"

$ButtonCancel = New-Object System.Windows.Forms.Button
$ButtonCancel.text = “&Cancel”
$ButtonCancel.Location = '120,467'
$ButtonCancel.size = '75,23'
$ButtonCancel.Anchor = 'Bottom, Left'
$ButtonCancel.add_Click({$Form.close()})
$Form.Controls.Add($ButtonCancel)

$ButtonOK = New-Object System.Windows.Forms.Button
$ButtonOK.Location = '245,467'
$ButtonOK.Size = '75,23'
$ButtonOK.Name = 'ButtonOK'
$ButtonOK.Text = 'OK'
$ButtonOK.add_Click($ButtonOK_Click)
$Form.Controls.Add($ButtonOK)
$Form.Controls.Add($TreeView)
$Form.ShowDialog() > $null

$script:SelectedOU

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

一种方法是在编写节点文本之前添加一个额外的检查,查找当前级别未检查的内容,这只发生在Get-CheckedNodes函数中。

因此,如果未检查当前级别中的至少一个节点,则将检查的节点写入输出,否则不执行任何操作。并且,如果在当前级别检查所有节点,则将检查父级,并将其文本写入输出。此外,如果检查节点,则其所有子节点都将是。所以这应该适用于所有情况。

Function Get-CheckedNodes($nodes) {

    $allChecked = $true
    foreach ($n in $Nodes) 
    {
        if (!$n.checked) {
            $allChecked = $false
            break
        }
    }
    foreach ($n in $Nodes) 
    {
        if ($n.nodes.count -gt 0) {
            Get-CheckedNodes $n.nodes
        }
        if ($n.checked -and $allChecked -eq $false) {
            Write-Output $n.Name
        }           
    }   
}