使用 Powershell 刷新数组复选框

Refresh Array checkboxes with Powershell

我正在尝试创建一个脚本,让用户可以从下拉列表中选择服务器。每个服务器都映射到一个唯一的数组,该数组进入 foreach 循环。循环遍历数组并在表单上打印一个复选框,其中包含数组中的值。这没有问题。问题是当我从下拉列表中 select 不同的服务器并单击“Select 服务器”按钮时,数组中的新值不会覆盖现有值。换句话说,表单上的复选框值不会更新为新的数组值。我希望发生的是,当您单击“Select 服务器”按钮时,复选框值会更新以反映与其相应服务器关联的数组值。

这里有一个例子。

  1. 从下拉列表中选择 ServerA
  2. Select 'Select Server'
  3. 以下复选框将在复选框的表单中列出:@('Zero','One','Two','Three')
  4. 现在,如果您单击 ServerB 和 select“Select 服务器”,我希望新的复选框会使用这些值覆盖现有的复选框:@('0','1', '2','3')

不幸的是,这些值没有更新。当“Select 服务器”按钮被 select 编辑时,我需要更新数组值...我查看了论坛并找到了一些可能的解决方案,但它们似乎都不尽如人意。

提前致谢。

function GenerateForm 
{   
$PC=
{
    $hostname = $dropdown.SelectedItem
    
    if ($hostname -eq "ServerA")

        { $CheckBoxLabels = @('Zero','One','Two','Three')
        }
    elseif($hostname -eq "ServerB")
        {
           $CheckBoxLabels = @('0','1','2','3')
     }
        
    $name = New-Object System.Windows.Forms.Label -Property @{
    Text = "Start Time"
    Location = "900, 220"
    ForeColor = "Black"
    Height = 22
    Width = 200
    }
    $form1.Controls.Add($hostname)
        
    $CheckBoxCounter = 1
    
    $CheckBoxes = foreach($Label in $CheckBoxLabels) 
    {   
        $CheckBox = New-Object System.Windows.Forms.CheckBox        
        $CheckBox.UseVisualStyleBackColor = $True
        $System_Drawing_Size = New-Object System.Drawing.Size
        $System_Drawing_Size.Width = 104
        $System_Drawing_Size.Height = 24
        $CheckBox.Size = $System_Drawing_Size
        $CheckBox.TabIndex = 2
    
        $CheckBox.Text = $Label
        
        $System_Drawing_Point = New-Object System.Drawing.Point
        $System_Drawing_Point.X = 27
        # Make sure to vertically space them dynamically, counter comes in handy
        $System_Drawing_Point.Y = 200 + (($CheckBoxCounter - 1) * 31) #Controls location on Y axis
        $CheckBox.Location = $System_Drawing_Point
        $CheckBox.DataBindings.DefaultDataSourceUpdateMode = 0

        # Give it a unique name based on our counter
        $CheckBox.Name = "CheckBox$CheckBoxCounter"

       $form1.Controls.Add($CheckBox)

        # return object ref to array
        $Global:CheckBox
        # increment our counter
        $CheckBoxCounter++
    }
    }

    $form1 = New-Object System.Windows.Forms.Form
    $form1.Text = "UCCE Log Collector - Version 2.0"
    $form1.Name = "form1"
    $form1.DataBindings.DefaultDataSourceUpdateMode = 0
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Width = 1150
    $System_Drawing_Size.Height = 500
    $form1.ClientSize = $System_Drawing_Size

$dropdown = New-Object System.Windows.Forms.ListBox
$dropdown.Location = New-Object System.Drawing.Point(10,50)
$dropdown.Size = New-Object System.Drawing.Size(100,20)
$dropdown.Height = 80

[void] $dropdown.Items.Add('ServerA')
[void] $dropdown.Items.Add('ServerB')


$form1.Controls.Add($dropdown)

    ######### Select Server Button
    $SelectPC = New-Object System.Windows.Forms.Button
    $SelectPC.TabIndex = 4
    $SelectPC.Name = "SelectPC"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Width = 120
    $System_Drawing_Size.Height = 30
    $SelectPC.Size = $System_Drawing_Size
    $SelectPC.UseVisualStyleBackColor = $True
    $SelectPC.Text = "Select Server"
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 0 # 0
    $System_Drawing_Point.Y = 150 #150
    $SelectPC.Location = $System_Drawing_Point
    $SelectPC.DataBindings.DefaultDataSourceUpdateMode = 0
    $SelectPC.add_Click($PC)

    $form1.Controls.Add($SelectPC)
    
        $result = $form1.ShowDialog()
    $result

}
GenerateForm

根据请求 to accommodate a variable number of properties for each host, first we'll create a Panel 保留我们的 CheckBoxes 并将其添加到我们的 Form...

# Create a Panel to contain the dynamic collection of CheckBoxes
$HostPropertiesPanel = New-Object -TypeName 'System.Windows.Forms.Panel' -Property @{
    # To illustrate the changing Size of the Panel
    BackColor = [System.Drawing.Color]::GreenYellow
    Location  = New-Object -TypeName 'System.Drawing.Point' -Property @{
        X = 27
        Y = 200
    }
    Name      = 'HostPropertiesPanel'
    Size      = [System.Drawing.Size]::Empty
}
$form1.Controls.Add($HostPropertiesPanel)

这消除了我们自己跟踪 CheckBoxes 的需要,因为我们知道它们都包含在这个 Panel 中。 Size 最初是 Empty,因为在选择主机之前不会显示 CheckBox

Click/$PC 中,我们将更改主机属性的定义方式...

# Set $hostProperties to a Hashtable array for the corresponding value of $hostname
# The IsChecked values are arbitrary for demonstration purposes
#TODO: Replace if...elseif with a switch statement; see "help about_Switch"
$hostProperties = if ($hostname -eq "ServerA") {
    @{ Label = 'Zero';  IsChecked = $false },
    @{ Label = 'One';   IsChecked = $true },
    @{ Label = 'Two';   IsChecked = $true },
    @{ Label = 'Three'; IsChecked = $false }
}
elseif ($hostname -eq "ServerB") {
    @{ Label = '0'; IsChecked = $true },
    @{ Label = '1'; IsChecked = $false },
    @{ Label = '2'; IsChecked = $false },
    @{ Label = '3'; IsChecked = $true }
}
elseif ($hostname -eq "ServerC") {
    @{ Label = 'A'; IsChecked = $true },
    @{ Label = 'B'; IsChecked = $true },
    @{ Label = 'C'; IsChecked = $false }
}
elseif ($hostname -eq "ServerD") {
    # Create a property (Hashtable) for each day of the week
    [Enum]::GetNames([DayOfWeek]) | ForEach-Object -Process {
        @{
            Label     = $_
            # Check the box if the day name has an odd number of vowels
            IsChecked = [Regex]::Matches($_, '[aeiou]').Count % 2 -eq 1
        }
    }
}
else {
    # Oops!  A host with no properties defined was selected...
}

我们不是使用一个数组存储标签,另一个数组存储 CheckBox 状态,而是根据选择的主机获得一个 Hashtable 数组并将其存储在 $hostProperties.

在我们创建新的 CheckBoxes 之前,我们必须从 $HostPropertiesPanel 中删除所有现有的,并根据所选主机属性的 Length 调整其大小...

# Remove all existing CheckBoxes from the Panel
$HostPropertiesPanel.Controls.Clear()
# Resize the Panel to accommodate the new count of host properties
$HostPropertiesPanel.Size = New-Object -TypeName 'System.Drawing.Size' -Property @{
    Width  = 104
    Height = if ($hostProperties.Length -gt 0) {
        ($hostProperties.Length - 1) * 31 + 24
    }
    else {
        0
    }
}

然后我们只需要调整创建和配置每个 CheckBox...

的代码
for ($index = 0; $index -lt $hostProperties.Length; $index++) {
    $CheckBox = New-Object System.Windows.Forms.CheckBox
    $CheckBox.UseVisualStyleBackColor = $True
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Width = 104
    $System_Drawing_Size.Height = 24
    $CheckBox.Size = $System_Drawing_Size
    $CheckBox.TabIndex = 2

    $CheckBox.Text = $hostProperties[$index].Label
    $CheckBox.Checked = $hostProperties[$index].IsChecked

    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 0
    # Make sure to vertically space them dynamically, counter comes in handy
    $System_Drawing_Point.Y = $index * 31 #Controls location on Y axis
    $CheckBox.Location = $System_Drawing_Point
    $CheckBox.DataBindings.DefaultDataSourceUpdateMode = 0

    # Give it a unique name based on our counter
    $CheckBox.Name = "CheckBox$index"

    $HostPropertiesPanel.Controls.Add($CheckBox)
}

关键变化是使用 $hostProperties$index 的当前值检索新 CheckBoxTextChecked 值。

最后的更改是更新主机名列表...

$dropdown.Items.AddRange(
    @('ServerA', 'ServerB', 'ServerC', 'ServerD', 'ServerX')
)
$form1.Controls.Add($dropdown)

完整的脚本如下所示...

function GenerateForm {
    $PC = {
        $hostname = $dropdown.SelectedItem
        # Set $hostProperties to a Hashtable array for the corresponding value of $hostname
        # The IsChecked values are arbitrary for demonstration purposes
        #TODO: Replace if...elseif with a switch statement; see "help about_Switch"
        $hostProperties = if ($hostname -eq "ServerA") {
            @{ Label = 'Zero';  IsChecked = $false },
            @{ Label = 'One';   IsChecked = $true },
            @{ Label = 'Two';   IsChecked = $true },
            @{ Label = 'Three'; IsChecked = $false }
        }
        elseif ($hostname -eq "ServerB") {
            @{ Label = '0'; IsChecked = $true },
            @{ Label = '1'; IsChecked = $false },
            @{ Label = '2'; IsChecked = $false },
            @{ Label = '3'; IsChecked = $true }
        }
        elseif ($hostname -eq "ServerC") {
            @{ Label = 'A'; IsChecked = $true },
            @{ Label = 'B'; IsChecked = $true },
            @{ Label = 'C'; IsChecked = $false }
        }
        elseif ($hostname -eq "ServerD") {
            # Create a property (Hashtable) for each day of the week
            [Enum]::GetNames([DayOfWeek]) | ForEach-Object -Process {
                @{
                    Label     = $_
                    # Check the box if the day name has an odd number of vowels
                    IsChecked = [Regex]::Matches($_, '[aeiou]').Count % 2 -eq 1
                }
            }
        }
        else {
            # Oops!  A host with no properties defined was selected...
        }

        # Don't execute any layout logic until all changes are complete
        $HostPropertiesPanel.SuspendLayout()
        # Remove all existing CheckBoxes from the Panel
        $HostPropertiesPanel.Controls.Clear()
        # Resize the Panel to accommodate the new count of host properties
        $HostPropertiesPanel.Size = New-Object -TypeName 'System.Drawing.Size' -Property @{
            Width  = 104
            Height = if ($hostProperties.Length -gt 0) {
                ($hostProperties.Length - 1) * 31 + 24
            }
            else {
                0
            }
        }

        for ($index = 0; $index -lt $hostProperties.Length; $index++) {
            $CheckBox = New-Object System.Windows.Forms.CheckBox
            $CheckBox.UseVisualStyleBackColor = $True
            $System_Drawing_Size = New-Object System.Drawing.Size
            $System_Drawing_Size.Width = 104
            $System_Drawing_Size.Height = 24
            $CheckBox.Size = $System_Drawing_Size
            $CheckBox.TabIndex = 2

            $CheckBox.Text = $hostProperties[$index].Label
            $CheckBox.Checked = $hostProperties[$index].IsChecked

            $System_Drawing_Point = New-Object System.Drawing.Point
            $System_Drawing_Point.X = 0
            # Make sure to vertically space them dynamically, counter comes in handy
            $System_Drawing_Point.Y = $index * 31 #Controls location on Y axis
            $CheckBox.Location = $System_Drawing_Point
            $CheckBox.DataBindings.DefaultDataSourceUpdateMode = 0

            # Give it a unique name based on our counter
            $CheckBox.Name = "CheckBox$index"

            $HostPropertiesPanel.Controls.Add($CheckBox)
        }

        # All changes are complete, so resume layout logic
        $HostPropertiesPanel.ResumeLayout()
    }

    $form1 = New-Object System.Windows.Forms.Form
    $form1.Text = "UCCE Log Collector - Version 2.0"
    $form1.Name = "form1"
    $form1.DataBindings.DefaultDataSourceUpdateMode = 0
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Width = 1150
    $System_Drawing_Size.Height = 500
    $form1.ClientSize = $System_Drawing_Size

    $dropdown = New-Object System.Windows.Forms.ListBox
    $dropdown.Location = New-Object System.Drawing.Point(10, 50)
    $dropdown.Size = New-Object System.Drawing.Size(100, 20)
    $dropdown.Height = 80

    $dropdown.Items.AddRange(
        @('ServerA', 'ServerB', 'ServerC', 'ServerD', 'ServerX')
    )
    $form1.Controls.Add($dropdown)

    ######### Select Server Button
    $SelectPC = New-Object System.Windows.Forms.Button
    $SelectPC.TabIndex = 4
    $SelectPC.Name = "SelectPC"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Width = 120
    $System_Drawing_Size.Height = 30
    $SelectPC.Size = $System_Drawing_Size
    $SelectPC.UseVisualStyleBackColor = $True
    $SelectPC.Text = "Select Server"
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 0 # 0
    $System_Drawing_Point.Y = 150 #150
    $SelectPC.Location = $System_Drawing_Point
    $SelectPC.DataBindings.DefaultDataSourceUpdateMode = 0
    $SelectPC.add_Click($PC)

    $form1.Controls.Add($SelectPC)

    # Create a Panel to contain the dynamic collection of CheckBoxes
    $HostPropertiesPanel = New-Object -TypeName 'System.Windows.Forms.Panel' -Property @{
        # To illustrate the changing Size of the Panel
        BackColor = [System.Drawing.Color]::GreenYellow
        Location  = New-Object -TypeName 'System.Drawing.Point' -Property @{
            X = 27
            Y = 200
        }
        Name      = 'HostPropertiesPanel'
        Size      = [System.Drawing.Size]::Empty
    }
    $form1.Controls.Add($HostPropertiesPanel)

    $name = New-Object System.Windows.Forms.Label -Property @{
        Text      = "Start Time"
        Location  = "900, 220"
        ForeColor = "Black"
        Height    = 22
        Width     = 200
    }
    $form1.Controls.Add($name)

    $result = $form1.ShowDialog()
    $result
}
GenerateForm

另一种方法,特别是对于大量主机属性,是将 Panel 及其内容替换为 CheckedListBox