Powershell:当事件处理程序在 for 循环内时,复选框更改事件不会给出有效结果
Powershell : When event handler is inside for loop, Checkbox change event does not give valid result
我创建了一组复选框。我可以分别为每个复选框创建一个事件处理程序,但因为这将是冗长的代码,所以我想如果我可以使用循环创建它们。当事件处理程序写在循环内时,事件正在处理,但显示的结果是错误的,即 -> 当我 select 我选中事件处理框时,但 $checkBox_Charts[$i].Checked
总是返回 False
该框是选中还是未选中。
编辑 1:
- 我意识到即使在任何复选框上引发 checked 事件,这段代码也会返回 for 循环中最后一个元素的选中状态,
- 添加完整代码
代码:
function whichCharts(){
Write-Host "CP1: in whichCharts"
foreach ($key_chart in $charts.Keys){
Write-Host $charts[$key_chart]
}
}
function checkbox_test{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# Set the size of your form
$Form = New-Object System.Windows.Forms.Form
$Form.width = 1000
$Form.height = 600
$Form.Text = ”My First Form with a working checkbox”
# Set the font of the text to be used within the form
$Font = New-Object System.Drawing.Font("Times New Roman",12)
$Form.Font = $Font
$charts = @("x","y","z")
$checkBox_Charts =[System.Windows.Forms.checkbox[]]::new(3)
$index_checkBox_Charts=0
for ($i=0;$i -lt $charts.Count; $i++){
$CheckBox = new-object System.Windows.Forms.checkbox
$height = (60*$i)+20
$CheckBox.Location = new-object System.Drawing.Size(100,$height)
$CheckBox.Size = '150,50'
$CheckBox.Text = $charts[$i]
$CheckBox.Checked = $false
$checkBox_Charts[$i] = $CheckBox
}
# Add an OK button
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = '50,500'
$OKButton.Size = '100,40'
$OKButton.Text = "OK"
$OKButton.DialogResult=[System.Windows.Forms.DialogResult]::OK
#Add a cancel button
$CancelButton = new-object System.Windows.Forms.Button
$CancelButton.Location = '255,100'
$CancelButton.Size = '100,40'
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult=[System.Windows.Forms.DialogResult]::Cancel
# Create a group that will contain your radio buttons
$MyGroupBox = New-Object System.Windows.Forms.GroupBox
$MyGroupBox.Location = '40,30'
$MyGroupBox.size = '800,400'
$MyGroupBox.text = "Do you like Cheese?"
# Add all the GroupBox controls on one line
$MyGroupBox.Controls.AddRange(@($checkBox_Charts))
$Form.Controls.AddRange(@($MyGroupBox,$OKButton,$CancelButton))
########### This is the important piece ##############
# #
# Do something when the state of the checkbox changes #
#######################################################
for($i=0; $i -lt 2; $i++){
$checkBox_Charts[$i].Add_CheckStateChanged({
Write-Host "CP2: in Add_CheckStateChanged " + $checkBox_Charts[$i].Checked
Write-Host $checkBox_Charts[$i]
Write-Host $i})
}
# Activate the form
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
#Call the function
checkbox_test
在 CheckStateChanged
事件的脚本块中,变量 $i
未知。要使它的值在那里可用,您必须将它存储在复选框可以读取的 属性 中。最好的地方是复选框自己的 Tag
属性.
在您的代码中,像这样创建复选框:
$charts = "x","y","z" # no need to surround this with @()
$checkBox_Charts = [System.Windows.Forms.checkbox[]]::new($charts.Count)
for ($i = 0; $i -lt $charts.Count; $i++){
$CheckBox = new-object System.Windows.Forms.checkbox
$height = (60*$i)+20
$CheckBox.Location = new-object System.Drawing.Size(100,$height)
$CheckBox.Size = '150,50'
$CheckBox.Text = $charts[$i]
$CheckBox.Checked = $false
# save the index $i in the Tag property of the checkbox itself
$CheckBox.Tag = $i
$CheckBox.Add_CheckStateChanged({
# inside this scriptblock, the variable $i is unknown
# so we use the index value stored in the Tag property earlier
Write-Host "CP2: in Add_CheckStateChanged $($this.Checked)"
Write-Host "CheckBox index: $($this.Tag)"
Write-Host $checkBox_Charts[$this.Tag]
Write-Host
})
$checkBox_Charts[$i] = $CheckBox
}
然后删除这里的代码:
########### This is the important piece ##############
# #
# Do something when the state of the checkbox changes #
#######################################################
for($i=0; $i -lt 2; $i++){
$checkBox_Charts[$i].Add_CheckStateChanged({
Write-Host "CP2: in Add_CheckStateChanged " + $checkBox_Charts[$i].Checked
Write-Host $checkBox_Charts[$i]
Write-Host $i})
}
因为这一切都是在之前创建复选框时完成的(并且不会像您注意到的那样工作)
作为旁注:
更改此 obsolete/deprecated 代码:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
进入
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
straighten the curly quotes you have in $Form.Text = ”My First Form with a working checkbox”
to become $Form.Text = "My First Form with a working checkbox"
.
They won't hurt you in this case, but using curly quotes in code can lead to numerous weird problems. Never use them in code.
在控件的事件处理程序中,$this
自动变量指的是控件本身
我创建了一组复选框。我可以分别为每个复选框创建一个事件处理程序,但因为这将是冗长的代码,所以我想如果我可以使用循环创建它们。当事件处理程序写在循环内时,事件正在处理,但显示的结果是错误的,即 -> 当我 select 我选中事件处理框时,但 $checkBox_Charts[$i].Checked
总是返回 False
该框是选中还是未选中。
编辑 1:
- 我意识到即使在任何复选框上引发 checked 事件,这段代码也会返回 for 循环中最后一个元素的选中状态,
- 添加完整代码
代码:
function whichCharts(){
Write-Host "CP1: in whichCharts"
foreach ($key_chart in $charts.Keys){
Write-Host $charts[$key_chart]
}
}
function checkbox_test{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# Set the size of your form
$Form = New-Object System.Windows.Forms.Form
$Form.width = 1000
$Form.height = 600
$Form.Text = ”My First Form with a working checkbox”
# Set the font of the text to be used within the form
$Font = New-Object System.Drawing.Font("Times New Roman",12)
$Form.Font = $Font
$charts = @("x","y","z")
$checkBox_Charts =[System.Windows.Forms.checkbox[]]::new(3)
$index_checkBox_Charts=0
for ($i=0;$i -lt $charts.Count; $i++){
$CheckBox = new-object System.Windows.Forms.checkbox
$height = (60*$i)+20
$CheckBox.Location = new-object System.Drawing.Size(100,$height)
$CheckBox.Size = '150,50'
$CheckBox.Text = $charts[$i]
$CheckBox.Checked = $false
$checkBox_Charts[$i] = $CheckBox
}
# Add an OK button
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = '50,500'
$OKButton.Size = '100,40'
$OKButton.Text = "OK"
$OKButton.DialogResult=[System.Windows.Forms.DialogResult]::OK
#Add a cancel button
$CancelButton = new-object System.Windows.Forms.Button
$CancelButton.Location = '255,100'
$CancelButton.Size = '100,40'
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult=[System.Windows.Forms.DialogResult]::Cancel
# Create a group that will contain your radio buttons
$MyGroupBox = New-Object System.Windows.Forms.GroupBox
$MyGroupBox.Location = '40,30'
$MyGroupBox.size = '800,400'
$MyGroupBox.text = "Do you like Cheese?"
# Add all the GroupBox controls on one line
$MyGroupBox.Controls.AddRange(@($checkBox_Charts))
$Form.Controls.AddRange(@($MyGroupBox,$OKButton,$CancelButton))
########### This is the important piece ##############
# #
# Do something when the state of the checkbox changes #
#######################################################
for($i=0; $i -lt 2; $i++){
$checkBox_Charts[$i].Add_CheckStateChanged({
Write-Host "CP2: in Add_CheckStateChanged " + $checkBox_Charts[$i].Checked
Write-Host $checkBox_Charts[$i]
Write-Host $i})
}
# Activate the form
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
#Call the function
checkbox_test
在 CheckStateChanged
事件的脚本块中,变量 $i
未知。要使它的值在那里可用,您必须将它存储在复选框可以读取的 属性 中。最好的地方是复选框自己的 Tag
属性.
在您的代码中,像这样创建复选框:
$charts = "x","y","z" # no need to surround this with @()
$checkBox_Charts = [System.Windows.Forms.checkbox[]]::new($charts.Count)
for ($i = 0; $i -lt $charts.Count; $i++){
$CheckBox = new-object System.Windows.Forms.checkbox
$height = (60*$i)+20
$CheckBox.Location = new-object System.Drawing.Size(100,$height)
$CheckBox.Size = '150,50'
$CheckBox.Text = $charts[$i]
$CheckBox.Checked = $false
# save the index $i in the Tag property of the checkbox itself
$CheckBox.Tag = $i
$CheckBox.Add_CheckStateChanged({
# inside this scriptblock, the variable $i is unknown
# so we use the index value stored in the Tag property earlier
Write-Host "CP2: in Add_CheckStateChanged $($this.Checked)"
Write-Host "CheckBox index: $($this.Tag)"
Write-Host $checkBox_Charts[$this.Tag]
Write-Host
})
$checkBox_Charts[$i] = $CheckBox
}
然后删除这里的代码:
########### This is the important piece ##############
# #
# Do something when the state of the checkbox changes #
#######################################################
for($i=0; $i -lt 2; $i++){
$checkBox_Charts[$i].Add_CheckStateChanged({
Write-Host "CP2: in Add_CheckStateChanged " + $checkBox_Charts[$i].Checked
Write-Host $checkBox_Charts[$i]
Write-Host $i})
}
因为这一切都是在之前创建复选框时完成的(并且不会像您注意到的那样工作)
作为旁注:
更改此 obsolete/deprecated 代码:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
进入
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing
straighten the curly quotes you have in
$Form.Text = ”My First Form with a working checkbox”
to become$Form.Text = "My First Form with a working checkbox"
.
They won't hurt you in this case, but using curly quotes in code can lead to numerous weird problems. Never use them in code.
在控件的事件处理程序中,$this
自动变量指的是控件本身