【问题标题】:PowerShell .NET Retrieve only parent node if all child nodes are selectedPowerShell .NET 如果选择了所有子节点,则仅检索父节点
【发布时间】:2015-03-12 08:09:29
【问题描述】:

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

在下面的示例中,如果您选择“汽车 > 蓝色”,它将返回:兰博基尼、玛莎拉蒂和蓝色。这是正确的,但我只想让它报告父级“蓝色”,因为所有内容都已选中。但是,当只选择了一辆汽车时,它应该只报告那辆汽车,而不是它的父级。

代码:

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

感谢您的帮助。

【问题讨论】:

    标签: .net winforms forms powershell


    【解决方案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
            }           
        }   
    }
    

    【讨论】:

    • 你的方法比我的努力好得多,也更容易阅读。我试图创建一个计数器来计算当前节点的总节点数。然后在此之后检查当前节点是否有节点,如果没有则增加计数器。但我无法让它正常工作。再次感谢 Micky 提供的出色解决方案!像梦一样工作:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多