Home > Enterprise >  PowerShell GUI: Add varied number of combo boxes in For Loop
PowerShell GUI: Add varied number of combo boxes in For Loop

Time:01-24

I have a PowerShell script that returns a $results array which can vary in length. I need to create a drop down for each of those results. Since the length of $results varies, I have the combo box creation in a for loop. However, not all of the combo boxes work; only the last one works.

Here is sample code below. It creates two labels and two combo boxes. ComboBox1 should update Label1 when ComboBox1.selected is changed and ComboBox2 should change Label2. However, the only ComboBox2 changes Label2 but ComboBox1 doesn't update Label1 and writes -1 out of bounds to the console. I'm unsure of how to get it to work for both ComboBoxes.

$form = New-Object System.Windows.Forms.Form
$form.StartPosition = "CenterScreen"
$form.Size = New-Object System.Drawing.Size(500, 300)
$form.Text = "TestForLoop-ComboBoxes"

$ComboBoxArr = @('ex0','ex1','ex3')
$results = @("result 1", "result2")
$x = 0
$y = 0
foreach($result in $results){
    $Label = New-Object System.Windows.Forms.Label
    $Label.Width = 170
    $Label.Height = 20
    $Label.Location = New-Object System.Drawing.Point(0, $y)
    $Label.Text = "Selected:"
    $form.controls.Add($Label)

    $ComboBox = New-Object System.Windows.Forms.ComboBox
    $ComboBox.Text = ""
    $ComboBox.width = 170
    $ComboBox.Location = New-Object System.Drawing.Point(0, ($y 20))
    $ComboBoxArr | ForEach-Object {[void] $ComboBox.Items.Add($_)}
    $ComboBox.add_SelectedIndexChanged({
        $selected = $ComboBox.SelectedIndex
        write-host $selected
        $Label.text = “Selected: $($DropBox.Text)”

    })
    $form.Controls.Add($ComboBox)
    
    $y  = 60
}

[void] $form.ShowDialog()

All help is appreciated!

CodePudding user response:

In order to update the correct label you need to somehow reference it. There are a number of ways you can do this but for this example we'll keep it simple and give both the label and combobox matching names. Then inside each combobox's SelectedIndexChanged eventhandler we find the correct label by matching the name to the combobox name. Inside the eventhandler the combobox should be referred to with the $this variable which is an automatic variable used to reference the owning object of the event.

Below is simplified code to demonstrate the main points.

$results = @('result 1', 'result2')
foreach ($result in $results) {
    $Label = New-Object System.Windows.Forms.Label
    $Label.Text = 'Selected:'
    $form.controls.Add($Label)
    # give the label a name
    $label.Name = $result

    $ComboBox = New-Object System.Windows.Forms.ComboBox
    # give the combobox the same name
    $ComboBox.Name = $result

    $ComboBox.add_SelectedIndexChanged({
            # reference the combobox using $this automatic variable
            $selected = $this.SelectedIndex
            Write-Host $selected
            # find the corresponding label using the matching name
            $label = $form.Controls | Where-Object { $_.Name -eq $this.Name -and $_ -is [System.Windows.Forms.Label] }
            # set the correct label's text
            $label.Text = “Selected: $($this.Text)”
        })
    $form.Controls.Add($ComboBox)
}

CodePudding user response:

You need to change the way you build the script block for the add_SelectedIndexChanged event.

Instead of:

$comboBox.SelectedIndex

You should use:

$this.SelectedIndex

Within that event $this will refer to the object executing the event. It will be a little more difficult to alter how you handle $Label and $DropBox since those are separate objects and are not accessible from $this.

  • Related