Проблема с областью .add_Click ({}) - PullRequest
2 голосов
/ 03 июня 2019

Я пытаюсь динамически назначать функции динамически создаваемым кнопкам.К сожалению, переменные не передаются в блок .add_Click({}), как я ожидаю.

Я уже пытался создать глобальную переменную $Global:Var, или ввести переменную в хеш-таблицу, или создал функцию, которую я вызвал в своем операторе click.Однако, самое большее, я получил только последний элемент из списка.

Как динамически выделить переменную для блока $var.add_Click({})?

Мой код:

Foreach ($Tenant in $Customer){
    if (-not ($Tenant -eq "")){
        $Tenant_Button = New-Object -TypeName System.Windows.Forms.Button
        $Tenant_Button.Location = New-Object -TypeName System.Drawing.Size(5, (15 + ($Tenant_Counter++ * 40)))
        $Tenant_Button.Size = New-Object -TypeName System.Drawing.Size(125, 35)
        $Tenant_Button.Text = $Tenant
        $Tenant_Button.Font = $Font_AccountButton

#Below starts the .add_Click({}) part!#
#Above variables are not accessible in the below part. 

        $Tenant_Button.add_Click({
            $Customer_Domain = ($CsvImport | Where-Object {$_.command_name -match "Admin $($Tenant_Button.Text)"}).command_name
            $DomainCounter = 0
            Foreach ($Domain in $Customer_Domain){
                $Button_Cust = New-Object -TypeName System.Windows.Forms.Button
                $Button_Cust.Location = New-Object -TypeName System.Drawing.Size(545, (25 + ($DomainCounter++ * 40)))
                $Button_Cust.Size = New-Object -TypeName System.Drawing.Size(125, 35)
                $Button_Cust.Text = $Domain

                $MainWindow.Controls.Add($Button_Cust)

                $Button_Cust.add_Click({
                    $FunctionIndex = [array]::IndexOf(($CsvImport).command_name, $Domain)
                    $Customer_Function = ($CsvImport[$FunctionIndex]).object_command

                    Invoke-Expression -Command $Customer_Function
                })
            }
         })
         $GroupBox_Acc.Controls.Add($Tenant_Button)

Как уже упоминалось ранее, сГлобальная переменная или функция или решение хеш-таблицы Мне удалось ввести одно содержимое переменной, но всегда только последнее.Следовательно, всем кнопкам была назначена одинаковая функция. Как я могу назначить двадцать различных функций двадцати различным кнопкам?

В завершение примера я предоставляю окружающий код.Введите «проблемный» код в команду $Button_Accounts.add_Click({}) (ее можно найти в конце кода ниже).

$CsvImport = Import-Csv -Delimiter ',' -LiteralPath 'C:\Test\Coding\commands.csv'

$MainWindow = New-Object -TypeName System.Windows.Forms.Form
$MainWindow.Text = 'Administrator Window'
$MainWindow.Width = 600
$MainWindow.Height = 555
$MainWindow.AutoSize = $true

$Button_Accounts = New-Object -TypeName System.Windows.Forms.Button
$Button_Accounts.Location = New-Object -TypeName System.Drawing.Size(25, 225)
$Button_Accounts.Size = New-Object -TypeName System.Drawing.Size(200, 75)
$Button_Accounts.Text = 'Accounts'

    $MainWindow.Controls.Add($Button_Accounts)

$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$GroupBox_Acc = New-Object -TypeName System.Windows.Forms.GroupBox

$Customer = $CsvImport.customer | Select-Object -Unique

$GroupBox_Acc.Text = 'Tenant List:'
$GroupBox_Acc.Location = New-Object -TypeName System.Drawing.Point(250, 25)
$GroupBox_Acc.Size = New-Object -TypeName System.Drawing.Size(270, 500)

$MainWindow.Controls.Add($GroupBox_Acc)

$Button_Accounts.Add_Click({
## Add above code here ##
})
$MainWindow.ShowDialog()

Пример содержимого csv:

command_group, Customer, command_name, object_commmand
Accounts, AAAA, Add Admin AP account, add_AP_admin_account
Accounts, AAAA, Add Admin AP Local account, add_AP_Local_admin_account
Accounts, BBBB, Add Admin ARL G account, add_ARLG_admin_account
Accounts, BBBB, Add Admin ARL CO account, add_ARLCO_admin_account

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Итак, давайте поговорим о том, почему это не работает в первую очередь.

Блок сценария {} использует последнее значение переменной, вызванной перед запуском.

@("RED","BLUE","GREEN") | %{
    $Team = $_
    $Button.add_Click({
        [System.Windows.MessageBox]::Show($Team)
    })
}
$MainWindow.ShowDialog()

Диалог всегда будет отображаться зеленым, независимо от того, нажму я красный или синийКнопка все равно будет только всплывающим зеленым.Это потому, что когда отправляется событие для Click, оно принимает то, что является самым последним значением переменной $Team.

Таким образом, исправление GetNewClosure()

@("RED","BLUE","GREEN") | %{
    $Team = $_
    $Button.add_Click({
        [System.Windows.MessageBox]::Show($Team)
    }.GetNewClosure())
}
$MainWindow.ShowDialog()

Что GetNewClosure() в блоке сценария {} делает, это берет текущее значение переменных и сохраняет их вместе с блоком сценария.Поэтому, если переменная изменяется, это не влияет на переменную, хранящуюся в блоке сценария.

Приведенный выше код возвращает красный цвет при нажатии на красный, синий при нажатии на синий и зеленый при нажатии на зеленый.

0 голосов
/ 03 июня 2019

Есть несколько способов написать это.Использование блоков скриптов, хранящихся в переменных, приятно и легко читаемо, без путаницы в области видимости переменных.

$clickOff = {
    $this | Get-Member
    $_
}

$btn_VMOff.add_Click($clickOff)

Другой вариант, если вы предпочитаете сохранять pe ClickOn и ClickOff-код в реальных функциях, это назначить обработчик.как это:

Function ClickOff
{ 
    $this | get-member
    $_
}

$btn_VMOff.add_Click(${function:ClickOff})
...