Windows forms - add data to list view on button click [duplicate]

I have a winform application which populate some data after I click on $button_UpdateTS, how do I add the data stored in a variable, that comes available after I click on that button ?

The data I want in my list view is stored in an array called $results

$button_UpdateTS = New-Object System.Windows.Forms.Button
$button_UpdateTS.Location = New-Object System.Drawing.Size(15, 954)
$button_UpdateTS.Size = New-Object System.Drawing.Size(320, 32)
$button_UpdateTS.TextAlign = "MiddleCenter"
$button_UpdateTS.Text = “Update Tasksequence”
$button_UpdateTS.Add_Click( { $Results = Set-DynamicVariables 
-Manufacturer "$($listview_Vendor.SelectedItems)" 
-TSPackageID "$($ListView_Tasksequences.SelectedItems.SubItems[1].Text)" -WhatIf })
    $Form.Controls.Add($button_UpdateTS)

Which gives me :

$Results = 
SKUNotExistsDriverName    : XPS Notebook 9560
SKUNotExistsDriverID      : PS10053F
SKUNotExistsDriverSKU     : 07BE
SKUNotExistsDriverVersion : A12
SKUNotExistsBIOSName      : XPS Notebook 9560
SKUNotExistsBIOSID        : PS10053E
SKUNotExistsBIOSSKU       : 07BE
SKUNotExistsBIOSVersion   : 1.15.0

This is the list I want it stored in :

$Global:listview_NotExists_SKU = New-Object System.Windows.Forms.ListView
$listview_NotExists_SKU.Location = New-Object System.Drawing.Size(515, 670)
$listview_NotExists_SKU.Size = New-Object System.Drawing.Size(486, 235)
$listview_NotExists_SKU.View = "Details"
$listview_NotExists_SKU.FullRowSelect = $true
$listview_NotExists_SKU.MultiSelect = $true
$listview_NotExists_SKU.Sorting = "None"
$listview_NotExists_SKU.AllowColumnReorder = $true
$listview_NotExists_SKU.GridLines = $true
$listview_NotExists_SKU.Add_ColumnClick( { SortListView $this $_.Column })
$Form.Controls.Add($listview_NotExists_SKU)

I tried with this function, but that does not work:

Function Get-Results {
        ForEach ($Result in $Results) {
            $listview_NotExists_SKU.Items.Add($Result) 
       }
}

$Form.Add_Shown( { $Form.Load; Get-results })

Because an event-handling script block added with e.g. .Add_Click() runs in in a child scope of the caller, assigning to variable $Results there ($Results = ...) creates a scope-local variable that neither the scope in which the event handler was set up nor subsequently invoked event handlers can see.

To create a variable in the script scope, which subsequently invoked event handlers can see as well[1], use the $script: scope specifier:

$button_UpdateTS.Add_Click( { $script:Results = ... } )

Note:

  • If the scope in which the event handlers are set up isn't the script scope (e.g., if the code is inside a function) and you want to more generically reference that scope from within an event handler, use Set-Variable -Scope 1 -Name Results -Value ..., which targets the respective parent scope.[1]

  • An alternative to setting a variable in the parent scope explicitly is to use a hashtable defined in the parent scope whose entries can be used in lieu of variables that the event-handler script blocks can modify too.[2] See this answer for an example.


[1] For more information about scopes in PowerShell, see the bottom section of this answer.

[2] This technique works, because even though the variable containing the hashtable is defined in the parent scope, the child scope can access its value and modify the entries of the referenced hashtable object rather than the variable itself.