locked
Second Combobox populated but not showing first value RRS feed

  • Question

  • Hello to all,
    as before, i am searching for advice. I have two combo boxes. First for main version selection and second for service pack. Selecting the main version populates the service pack values, but it does not show the first value in the second combo box before clicked on.
    What would be the correct way to achieve this? Using an event on second combo box when its populated? Or different refresh?

    Here is my code:

    # Create main form.
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.Application]::EnableVisualStyles()
    
    $Form                            = New-Object system.Windows.Forms.Form
    $Form.ClientSize                 = '600,400'
    $Form.text                       = "Software Installer"
    $Form.TopLevel                    = $true
    $form.startposition              = 'centerscreen'
    $form.FormBorderStyle            = 'Fixed3D'
    $form.Icon                       = [System.Drawing.SystemIcons]::WinLogo
    
    #Servicepack arrays for each version
    $2016=[collections.arraylist]@(
    	[pscustomobject]@{Name='2016 Service pack 1';Value='2016SP1'}
    	[pscustomobject]@{Name='2016 Service pack 2';Value='2016SP2'}
        [pscustomobject]@{Name='2016 Service pack 3';Value='2016SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2016SP4'}
    )
    
    $2016i=[collections.arraylist]@(
            [pscustomobject]@{Name='2016i Service pack 1';Value='2016iSP1'}
            [pscustomobject]@{Name='2016i Service pack 2';Value='2016iSP2'}
    )
    
    $2017=[collections.arraylist]@(
        [pscustomobject]@{Name='2017 Service pack 1';Value='2017SP1'}
        [pscustomobject]@{Name='2017 Service pack 2';Value='2017SP2'}
        [pscustomobject]@{Name='2017 Service pack 3';Value='2017SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2017SP4'}
        [pscustomobject]@{Name='2016 Service pack 5';Value='2017SP5'}
    )
    
    # Add version combobox. Use array for datasource.
    $ComboVersion                  = New-Object system.Windows.Forms.ComboBox
    $ComboVersion.DropDownStyle    = [System.Windows.Forms.ComboBoxStyle]::DropDownList
    $ComboVersion.text             = "Select Version"
    $ComboVersion.width            = 280
    $ComboVersion.height           = 20
    $ComboVersionItems=[collections.arraylist]@(
    	[pscustomobject]@{Name='TStructures 2016';Value=$2016}
    	[pscustomobject]@{Name='TStructures 2016i';Value=$2016i}
        [pscustomobject]@{Name='TStructures 2017';Value=$2017}
    )
    $ComboVersion.DataSource=$ComboVersionItems
    $ComboVersion.DisplayMember='Name'
    $ComboVersion.location         = New-Object System.Drawing.Point(150,40)
    $ComboVersion.Font             = 'Microsoft Sans Serif,10'
    
    # Add Service pack combobox. Use slected index value to load array items.
    $ComboServicePack                  = New-Object system.Windows.Forms.ComboBox
    $ComboServicePack.DropDownStyle    = [System.Windows.Forms.ComboBoxStyle]::DropDownList
    $ComboServicePack.text             = "Select ServicePack"
    $ComboServicePack.width            = 280
    $ComboServicePack.height           = 20
    #$ComboServicePack.DataSource=$option
    $ComboServicePack.DisplayMember='Name'
    $ComboServicePack.location         = New-Object System.Drawing.Point(150,80)
    $ComboServicePack.Font             = 'Microsoft Sans Serif,10'
    
    
    $ComboVersion_SelectedIndexChanged=
    {
        $option = $ComboVersion.SelectedItem.value
        $ComboServicePack.Items.Clear()
        foreach ($item in $option)
        {
            $ComboServicePack.Items.Add($item)
        }
    }
    $ComboVersion.add_SelectedIndexChanged($ComboVersion_SelectedIndexChanged)
    
    $Form.controls.AddRange(@($ComboVersion,$ComboServicePack))
    [void]$form.ShowDialog()


    • Edited by OndrejSK Monday, January 27, 2020 11:42 AM
    Monday, January 27, 2020 11:41 AM

Answers

  • The most important thing about building forms is consistency and correct use of properties and methods.  I have redone this to show you newer methods of easily building forms.  This approach wil force the second combobox to be populated.

    #Servicepack arrays for each version
    $2016=[collections.arraylist]@(
    	[pscustomobject]@{Name='2016 Service pack 1';Value='2016SP1'}
    	[pscustomobject]@{Name='2016 Service pack 2';Value='2016SP2'}
        [pscustomobject]@{Name='2016 Service pack 3';Value='2016SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2016SP4'}
    )
    
    $2016i=[collections.arraylist]@(
            [pscustomobject]@{Name='2016i Service pack 1';Value='2016iSP1'}
            [pscustomobject]@{Name='2016i Service pack 2';Value='2016iSP2'}
    )
    
    $2017=[collections.arraylist]@(
        [pscustomobject]@{Name='2017 Service pack 1';Value='2017SP1'}
        [pscustomobject]@{Name='2017 Service pack 2';Value='2017SP2'}
        [pscustomobject]@{Name='2017 Service pack 3';Value='2017SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2017SP4'}
        [pscustomobject]@{Name='2016 Service pack 5';Value='2017SP5'}
    )
    
    $ComboVersionItems=[collections.arraylist]@(
    	[pscustomobject]@{Name='TStructures 2016';Value=$2016}
    	[pscustomobject]@{Name='TStructures 2016i';Value=$2016i}
        [pscustomobject]@{Name='TStructures 2017';Value=$2017}
    )
    
    
    # Create main form.
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.Application]::EnableVisualStyles()
    
    $Form = [system.Windows.Forms.Form]@{
        ClientSize = '600,400'
        Text = "Software Installer"
        TopLevel = $true
        startposition = 'centerscreen'
        FormBorderStyle = 'Fixed3D'
        Icon = [System.Drawing.SystemIcons]::WinLogo
    }
    
    # Add version combobox. Use array for datasource.
    $ComboVersion = [system.Windows.Forms.ComboBox]@{
        Location = '150,40'
        Size = '280,20'
        DropDownStyle = 'DropDownList'
        Text = 'Select Version'
        Font = 'Microsoft Sans Serif,10'
        DataSource = $ComboVersionItems
        DisplayMember = 'Name'
    }
    $Form.controls.Add($ComboVersion)
    $ComboVersion.add_SelectedIndexChanged({
        if($ComboVersion.SelectedIndex -ge 0){
            $ComboServicePack.Items.Clear()
            $ComboServicePack.Items.AddRange($ComboVersion.SelectedItem.value)
            $ComboServicePack.SelectedIndex = 0
        }
    })
    
    # Add Service pack combobox. Use slected index value to load array items.
    $ComboServicePack = [System.Windows.Forms.ComboBox]@{
        DropDownStyle = 'DropDownList'
        Text = 'Select ServicePack'
        Location = '150,80'
        Size = '280,20'
        DisplayMember = 'Name'
        Font = 'Microsoft Sans Serif,10'
    }
    $Form.controls.Add($ComboServicePack)
    
    $Form.add_Load({
        # change index to force execution of event
        $ComboVersion.SelectedIndex = 1
        $ComboVersion.SelectedIndex = 0
    })
    
    [void]$form.ShowDialog()



    \_(ツ)_/


    • Edited by jrv Monday, January 27, 2020 7:14 PM
    • Marked as answer by OndrejSK Tuesday, January 28, 2020 7:02 AM
    Monday, January 27, 2020 7:12 PM

All replies

  • You need to add an event to the first that sets the second as needed.

    Normally we use "SelectedIndexChanged" to cascade changes.  TO cause this event to fire you need to set the index in the "Load" event for the form.


    \_(ツ)_/


    • Edited by jrv Monday, January 27, 2020 6:26 PM
    Monday, January 27, 2020 6:24 PM
  • The most important thing about building forms is consistency and correct use of properties and methods.  I have redone this to show you newer methods of easily building forms.  This approach wil force the second combobox to be populated.

    #Servicepack arrays for each version
    $2016=[collections.arraylist]@(
    	[pscustomobject]@{Name='2016 Service pack 1';Value='2016SP1'}
    	[pscustomobject]@{Name='2016 Service pack 2';Value='2016SP2'}
        [pscustomobject]@{Name='2016 Service pack 3';Value='2016SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2016SP4'}
    )
    
    $2016i=[collections.arraylist]@(
            [pscustomobject]@{Name='2016i Service pack 1';Value='2016iSP1'}
            [pscustomobject]@{Name='2016i Service pack 2';Value='2016iSP2'}
    )
    
    $2017=[collections.arraylist]@(
        [pscustomobject]@{Name='2017 Service pack 1';Value='2017SP1'}
        [pscustomobject]@{Name='2017 Service pack 2';Value='2017SP2'}
        [pscustomobject]@{Name='2017 Service pack 3';Value='2017SP3'}
        [pscustomobject]@{Name='2016 Service pack 4';Value='2017SP4'}
        [pscustomobject]@{Name='2016 Service pack 5';Value='2017SP5'}
    )
    
    $ComboVersionItems=[collections.arraylist]@(
    	[pscustomobject]@{Name='TStructures 2016';Value=$2016}
    	[pscustomobject]@{Name='TStructures 2016i';Value=$2016i}
        [pscustomobject]@{Name='TStructures 2017';Value=$2017}
    )
    
    
    # Create main form.
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.Application]::EnableVisualStyles()
    
    $Form = [system.Windows.Forms.Form]@{
        ClientSize = '600,400'
        Text = "Software Installer"
        TopLevel = $true
        startposition = 'centerscreen'
        FormBorderStyle = 'Fixed3D'
        Icon = [System.Drawing.SystemIcons]::WinLogo
    }
    
    # Add version combobox. Use array for datasource.
    $ComboVersion = [system.Windows.Forms.ComboBox]@{
        Location = '150,40'
        Size = '280,20'
        DropDownStyle = 'DropDownList'
        Text = 'Select Version'
        Font = 'Microsoft Sans Serif,10'
        DataSource = $ComboVersionItems
        DisplayMember = 'Name'
    }
    $Form.controls.Add($ComboVersion)
    $ComboVersion.add_SelectedIndexChanged({
        if($ComboVersion.SelectedIndex -ge 0){
            $ComboServicePack.Items.Clear()
            $ComboServicePack.Items.AddRange($ComboVersion.SelectedItem.value)
            $ComboServicePack.SelectedIndex = 0
        }
    })
    
    # Add Service pack combobox. Use slected index value to load array items.
    $ComboServicePack = [System.Windows.Forms.ComboBox]@{
        DropDownStyle = 'DropDownList'
        Text = 'Select ServicePack'
        Location = '150,80'
        Size = '280,20'
        DisplayMember = 'Name'
        Font = 'Microsoft Sans Serif,10'
    }
    $Form.controls.Add($ComboServicePack)
    
    $Form.add_Load({
        # change index to force execution of event
        $ComboVersion.SelectedIndex = 1
        $ComboVersion.SelectedIndex = 0
    })
    
    [void]$form.ShowDialog()



    \_(ツ)_/


    • Edited by jrv Monday, January 27, 2020 7:14 PM
    • Marked as answer by OndrejSK Tuesday, January 28, 2020 7:02 AM
    Monday, January 27, 2020 7:12 PM
  • Hello jrv!
    Thank you very much for your replies! I was trying to use $Form.Add_Load, but even it polulated the second combo, no value was not show before clicking on it.

    Thank you for the redone example. It looks perfect - simple, functional and elegant. I totally agree with your statement "The most important thing about building forms is consistency and correct use of properties and methods."
    It may not look like that, when you look at my code, but i am trying to achieve that. I just need to continue learning forms and gather experience.

    There is one thing i do not understand in your example. If the change of selected index to 1 and then back to 0 is triggering the event to populate the second combo.
    So, my problem with the empty line in second combo was the incorrect method of populating it?


    • Edited by OndrejSK Tuesday, January 28, 2020 7:31 AM
    Tuesday, January 28, 2020 7:22 AM
  • Your code used many different ways to to assign values.  That was inconsistent.  Also the order and method of creating objects was inconsistent.  These shows that you are copying the code and editing it using what you have seen others do but without understanding why.  Take time to think about what each line is doing and why.  Learn what a form and controls are and how they are intended to work. All of the documentation is onlne.

    The reason for the index is clearly stated in the comment I added just so you would know why.  Always read new code carefully to be sure you understand what it is telling you.

    https://docs.microsoft.com/en-us/dotnet/framework/winforms/


    \_(ツ)_/

    Tuesday, January 28, 2020 9:47 AM