Powershell: когда обработчик событий находится внутри для l oop, событие изменения флажка не дает действительного результата - PullRequest
0 голосов
/ 04 апреля 2020

Я создал массив флажков. Я мог бы создать обработчик событий для каждого флажка отдельно, но так как это был бы длинный код, я подумал, что смогу создать их, используя l oop. Когда обработчик события записывается в l oop, событие обрабатывается, но показанный результат неверен, т. Е. -> когда я выбираю i-й флажок, событие обрабатывается, но $checkBox_Charts[$i].Checked всегда возвращает False независимо от того, установлено ли поле проверено или не проверено.

Редактировать 1:

  • Я понял, что даже когда проверяемое событие возникает в любом флажке, этот код возвращает проверенное состояние последнего элемента в течение l oop,
  • Добавление полного кода

Код:

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

1 Ответ

1 голос
/ 05 апреля 2020

Внутри блока сценария для события 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})

}

, поскольку теперь все это делается при создании флажков ранее (и не будет работать, как вы заметили)


В качестве sidenotes:
  • изменить этот устаревший / устаревший код:

    [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</p></li>
    <li><p>straighten the curly quotes you have in <code>$Form.Text = ”My First Form with a working checkbox”</code> to become <code>$Form.Text = "My First Form with a working checkbox"</code>.<br>
    They won't hurt you in this case, but using curly quotes in code can lead to numerous weird problems. <strong>Never use them in code</strong>.
    

Внутри обработчик события элемента управления, переменная $this automati c относится к самому элементу управления

...