simple GUI List Box returns no value

This topic contains 2 replies, has 2 voices, and was last updated by  Jeffrey Wagar 2 years, 1 month ago.

  • Author
    Posts
  • #28268

    Jeffrey Wagar
    Participant

    Googling many fine examples of the generic task of creating a drop-down list in PowerShell using .NET Assemblies, they all helpfully contain the following line of code for returning the item selected by the user (when they left-click the item then press the OK button).

    $OKButton.Add_Click({ $x = $objListBox.SelectedItem; $objForm.Close() })
    $objForm.Controls.Add($OKButton)

    Yet debugging their sample scripts reveals that $x is never assigned a value, nor is any error message or warning generated. What syntax error (or missing programming step) is occurring?

    Here is the simple, one page generic script running in PowerShell V4.0, tried on Windows 7 SP1 and Windows 8.1 Pro.

    # Load the .NET Assemblies containing the necessary Forms.

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

    # Create an object to hold the pop-up dialog box.

    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Select a Computer"
    $objForm.Size = New-Object System.Drawing.Size(300, 200)
    $objForm.StartPosition = "CenterScreen"

    # Create a label for the pop-up menu then attach it to the Drop-down List.

    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10, 20)
    $objLabel.Size = New-Object System.Drawing.Size(280, 20)
    $objLabel.Text = "Please select a computer:"
    $objForm.Controls.Add($objLabel)

    # Populate the Drop-down list.

    $objListBox = New-Object System.Windows.Forms.ListBox
    $objListBox.Location = New-Object System.Drawing.Size(10, 40)
    $objListBox.Size = New-Object System.Drawing.Size(260, 20)
    $objListBox.Height = 80

    [void] $objListBox.Items.Add("atl-dc-001")
    [void] $objListBox.Items.Add("atl-dc-002")
    [void] $objListBox.Items.Add("atl-dc-003")

    $objForm.Controls.Add($objListBox)

    # If the Enter key is left-clicked, select the highlighted menu item then close the pop-up menu.

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Enter") { $x = $objListBox.SelectedItem; $objForm.Close() }
    })

    # If the Escape key is left-clicked, simply close the pop-up menu.

    $objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Escape") { $objForm.Close() }
    })

    # Create an OK button.

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75, 120)
    $OKButton.Size = New-Object System.Drawing.Size(75, 23)
    $OKButton.Text = "OK"

    # If the OK button is left-clicked, select the highlighted menu item then close the pop-up menu.

    $OKButton.Add_Click({ $x = $objListBox.SelectedItem; $objForm.Close() })
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150, 120)
    $CancelButton.Size = New-Object System.Drawing.Size(75, 23)
    $CancelButton.Text = "Cancel"

    # If the Cancel button is left-clicked, simply close the pop-up menu.

    $CancelButton.Add_Click({ $objForm.Close() })
    $objForm.Controls.Add($CancelButton)

    # Shift the operating system focus to the pop-up menu then activate it — wait for the user response.

    $objForm.Topmost = $True

    $objForm.Add_Shown({ $objForm.Activate() })
    [void] $objForm.ShowDialog()

    Write-Host $x

  • #28269

    Vasken
    Participant

    $x is not accessible outside the Add_Click block by virtue of scope. If you try replacing the line with the following, it will hold the value of $x globally so that it's accessible when Write-Host needs it at the end of the script:

    $OKButton.Add_Click({ $global:x = $objListBox.SelectedItem; $objForm.Close() })

    Note that '$' goes in front of the 'global' specifier and not in front of the variable name itself like it would normally.

  • #28272

    Jeffrey Wagar
    Participant

    Thanks for the fast response, Vasken — you were exactly right!

    What caused the scope to change? Does each WPF form and WinForm have their own scope?

You must be logged in to reply to this topic.