首页 > 解决方案 > 使用 Powershell 刷新数组复选框

问题描述

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

这是一个例子。

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

不幸的是,这些值没有更新。I need to have the array values update when the "Select Server" button is selected... Ive looked around at forums and have found some possible solutions but they all seems to fall short.

先感谢您。

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

标签: arrayspowershellwinformscheckboxpowershell-5.0

解决方案


根据评论中的请求以容纳每个主机的可变数量的属性,首先我们将创建一个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 的需要,因为我们会知道它们都包含在 thisPanel中。Size最初是因为在选择主机之前Empty没有es 可显示。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获得一个 s 数组并将其存储在.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)
}

关键变化是使用in的 current检索 new 的TextChecked值。CheckBox$index$hostProperties

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

$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.


推荐阅读