Search code examples
powershellhashtablelistboxitem

Issue transfering ListboxItem and resolve in a Hashtable


Trying to learn and understand PowerShell better, I am trying to build a vocabulary trainer using forms in PowerShell.

The Vocabulary is stored in different topics, where each topic is stored in a hashtable.

Maybe I am approaching this the wrong way, but trying to work with the Listbox Item, I am not able to figure out, how to transfer the code in such way, that it goes into the correct Hashtable and shows the first Key.

I tried to combine several strings and tried to use Pipe to transfer the listbox item. Either ways I failed. Please have a look at the code, so I can further explain.

CLS
Add-Type -assembly System.Windows.Forms
$Script:Counter = 1

$Weekdays = [ordered]@{Monday = 'Montag';Tuesday = 'Dienstag';Wednesday = 'Mittwoch'}
$Months = [ordered]@{January = 'Januar';February = 'Februar';March = 'März'}
$Numbers =[ordered]@{One = 'Eins';Zwei = 'Two';Drei = 'Three'}

$Vocabulary = @{Weekdays = '$Weekdays';Months = '$months';Numbers = '$Numbers'}



$Main_Form = New-Object System.Windows.Forms.Form
$Main_Form.Icon = $objIcon
$Main_Form.Text ='Test Test Test'
$Main_Form.Size = '1000,600'
$Main_Form.StartPosition = "CenterScreen"
$Main_Form.AutoSize = $true
$Main_Form.BringToFront()

$Label = New-Object System.Windows.Forms.label
$Label.Location = '10,20'
$Label.Size = '200,60'
$Label.Font = New-Object System.Drawing.Font("Times New Roman",16,[System.Drawing.FontStyle]::Bold)
$Label.BackColor = "Transparent"
$Label.ForeColor = "Blue"
$Label.Text = 'Counter '+$Script:Counter
$Main_Form.Controls.Add($Label)

$ListBox = New-Object System.Windows.Forms.ListBox
$ListBox.Location = '20,80'
$ListBox.Size = '300,50'
$ListBox.Font = New-Object System.Drawing.Font("Times New Roman",20,[System.Drawing.FontStyle]::Bold)
$ListBox.Height = 150
$ListBox.items.AddRange($Vocabulary.Keys)
$Main_Form.Controls.Add($ListBox)

$Labelannouncement = New-Object System.Windows.Forms.label
$Labelannouncement.Location = '400,80'
$Labelannouncement.Size = '400,60'
$Labelannouncement.Font = New-Object System.Drawing.Font("Times New Roman",18,[System.Drawing.FontStyle]::Bold)
$Labelannouncement.BackColor = "Transparent"
$Labelannouncement.ForeColor = "Black"
$Labelannouncement.Text = 'Nothing chosen yet'
$Main_Form.Controls.Add($Labelannouncement)

$LabelContent = New-Object System.Windows.Forms.label
$LabelContent.Location = '400,160'
$LabelContent.Size = '400,60'
$LabelContent.Font = New-Object System.Drawing.Font("Times New Roman",18,[System.Drawing.FontStyle]::Bold)
$LabelContent.BackColor = "Transparent"
$LabelContent.ForeColor = "Black"
$Main_Form.Controls.Add($LabelContent)

$Labeltest = New-Object System.Windows.Forms.label
$Labeltest.Location = '400,250'
$Labeltest.Size = '400,60'
$Labeltest.Font = New-Object System.Drawing.Font("Times New Roman",18,[System.Drawing.FontStyle]::Bold)
$Labeltest.BackColor = "Transparent"
$Labeltest.ForeColor = "Red"
$Labeltest.Text = 'Test'
$Main_Form.Controls.Add($Labeltest)


$Button = New-Object System.Windows.Forms.Button
$Button.Location = '50,250'
$Button.Size = '200,75'
$Button.Font = New-Object System.Drawing.Font("Arial",16,[System.Drawing.FontStyle]::Bold)
$Button.Text = 'Next'
$Main_form.Controls.Add($Button)
    $ButtonClickEvent = {
    $Script:Counter++
    $Label.Text = "Counter $Script:Counter"
    $Labelannouncement.Text = $Listbox.SelectedItems
    $Labeltest.Text = ''
}
$Button.Add_Click($ButtonClickEvent)

$Main_Form.ShowDialog()

The Idea is, that when running the script, in the Listbox, I can choose from the 3 items. The target would be, that as soon as I have chosen one of the items, I would like to have the first Key of the related hashtable. So when I am choosing Weekdays, and press onto the Next button, the red Test should be replaced with "Monday".

The reason for the Hashtable called "$Vocabulary" is, to get the value:

$Vocabulary.item($Listbox.SelectedItem)

But now comes the question. To use the above example with "Monday", I would have to use the following code:

$($months.Keys)[0]

And here is the problem I am fighting with.

Do I have to pipe or to combine the result from the listbox.item and pass it on and how would I do that? For a test, I tried to add it as text to the last line.

$ButtonClickEvent = {
$Script:Counter++
$Label.Text = "Counter $Script:Counter"
$Labelannouncement.Text = $Listbox.SelectedItems
$Labeltest.Text = ''

So that when pressing onto Weekdays and then pressing the Next button, I would receive Monday as a red text.

Trying

$({$Vocabulary.item($Listbox.SelectedItem)}.Values)[0]

Did give me an index into a null array error and working with pipes, I haven't understood, how I would transfer to, so it does the same like:

$($months.Values)[0]

and the attempt using:

$($_.Values)[0]

Didn't help. Is there a way to solve this or is it a wrong attempt?

Thank you for any help, much appreciated

Mike


Solution

  • I would not store hashtables inside the $Vocabulary hashtable, but instead add arrays under each Key:

    $Weekdays = 'Montag','Dienstag','Mittwoch'
    $Months   = 'Januar','Februar','März'
    $Numbers  = 'Eins','Zwei','Drei'
    
    $Vocabulary = @{Weekdays = $Weekdays; Months = $Months; Numbers = $Numbers}
    

    Next, change the $ButtonClickEvent to become

    $ButtonClickEvent = {
        $Script:Counter++
        $Label.Text = "Counter $Script:Counter"
        $Labelannouncement.Text = $Listbox.SelectedItem
        $Labeltest.Text = $Vocabulary[$Listbox.SelectedItem][0]
    }
    
    1. $Listbox.SelectedItem (singular) gets the key name of the Vocabulary the user is interested in.
    2. $Vocabulary stores arrays under each key, and you want to show the first one, so simply use index [0] of the first item.

    P.S. When done, don't forget to clean up the form with $Main_Form.Dispose()

    Hope that helps