.add_Click({}) 的范围问题
Scope issue with .add_Click({})
我尝试将功能动态分配给动态创建的按钮。不幸的是,变量没有像我期望的那样传递到 .add_Click({})
块。
我已经尝试创建一个全局变量 $Global:Var
,或者在散列中输入变量 table,或者创建一个我在 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)
如前所述,使用全局变量或函数或散列 table 解决方案,我设法输入了一个变量内容,但始终只输入最后一个。因此,所有按钮都分配了相同的功能。 如何将二十种不同的功能分配给二十种不同的按钮?
为了完成示例,我提供了相关代码。在$Button_Accounts.add_Click({})
命令中输入'problematic'代码(可以在下面的代码末尾找到)命令。
$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
您可以通过几种不同的方式编写此内容。使用存储在变量中的脚本块很好且易于阅读,不会混淆变量范围。
$clickOff = {
$this | Get-Member
$_
}
$btn_VMOff.add_Click($clickOff)
另一种选择,如果您希望保留 p.e。 ClickOn 和 ClickOff 代码在实际功能中,是这样分配处理程序的:
Function ClickOff
{
$this | get-member
$_
}
$btn_VMOff.add_Click(${function:ClickOff})
所以让我们先谈谈为什么它不起作用。
脚本块 {}
正在使用 运行 之前调用的变量的最后一个值。
@("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()
所做的是获取变量的当前值并将它们与脚本块一起存储。因此,如果变量发生变化,它不会影响存储在脚本块中的变量。
以上代码returns点击红色时为红色,点击蓝色时为蓝色,点击绿色时为绿色。
我尝试将功能动态分配给动态创建的按钮。不幸的是,变量没有像我期望的那样传递到 .add_Click({})
块。
我已经尝试创建一个全局变量 $Global:Var
,或者在散列中输入变量 table,或者创建一个我在 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)
如前所述,使用全局变量或函数或散列 table 解决方案,我设法输入了一个变量内容,但始终只输入最后一个。因此,所有按钮都分配了相同的功能。 如何将二十种不同的功能分配给二十种不同的按钮?
为了完成示例,我提供了相关代码。在$Button_Accounts.add_Click({})
命令中输入'problematic'代码(可以在下面的代码末尾找到)命令。
$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
您可以通过几种不同的方式编写此内容。使用存储在变量中的脚本块很好且易于阅读,不会混淆变量范围。
$clickOff = {
$this | Get-Member
$_
}
$btn_VMOff.add_Click($clickOff)
另一种选择,如果您希望保留 p.e。 ClickOn 和 ClickOff 代码在实际功能中,是这样分配处理程序的:
Function ClickOff
{
$this | get-member
$_
}
$btn_VMOff.add_Click(${function:ClickOff})
所以让我们先谈谈为什么它不起作用。
脚本块 {}
正在使用 运行 之前调用的变量的最后一个值。
@("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()
所做的是获取变量的当前值并将它们与脚本块一起存储。因此,如果变量发生变化,它不会影响存储在脚本块中的变量。
以上代码returns点击红色时为红色,点击蓝色时为蓝色,点击绿色时为绿色。