Winforms 在多个复选框上生成并响应事件

Winforms 在多个复选框上生成并响应事件,winforms,powershell,Winforms,Powershell,我试图根据传递给表单创建函数的数组,创建一个带有多个复选框的表单。我可以根据我所处的复选框计数来计算正确的位置,但我(我认为)在处理事件时遇到了困难。我现在有这个(显然是部分代码) 复选框的创建是正确的,但是当我从函数返回$results时,它们都是真的。我的代码基于此,它可以工作,但有一个静态的复选框数量 function checkbox_test{ [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Wi

我试图根据传递给表单创建函数的数组,创建一个带有多个复选框的表单。我可以根据我所处的复选框计数来计算正确的位置,但我(我认为)在处理事件时遇到了困难。我现在有这个(显然是部分代码)

复选框的创建是正确的,但是当我从函数返回
$results
时,它们都是真的。我的代码基于此,它可以工作,但有一个静态的复选框数量

function checkbox_test{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

    $results = @{
        one = $true
        two = $true
    }
    $optionCount = 2

    # Set the size of your form
    $Form = New-Object System.Windows.Forms.Form
    $Form | Format-List *
    $form.FormBorderStyle = 'FixedDialog'
    $form.ShowInTaskbar = $false
    $Form.width = 300
    $Form.height = 150
    $Form.Text = ”Px Tools Updater”

    # 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

    # create your checkbox 
    $checkbox1 = new-object System.Windows.Forms.checkbox
    $checkbox1.Location = new-object System.Drawing.Size(10,7)
    $checkbox1.Size = new-object System.Drawing.Size(100,20)
    $checkbox1.Text = "One"
    $checkbox1.Checked = $true

    $Form.Controls.Add($checkbox1)

    # create your checkbox 
    $checkbox2 = new-object System.Windows.Forms.checkbox
    $checkbox2.Location = new-object System.Drawing.Size(10,27)
    $checkbox2.Size = new-object System.Drawing.Size(100,20)
    $checkbox2.Text = "Two"
    $checkbox2.Checked = $true
    $Form.Controls.Add($checkbox2)  

    # Add an OK button
    $OKButton = new-object System.Windows.Forms.Button
    $OKButton.Location = new-object System.Drawing.Size(10,70)
    $OKButton.Size = new-object System.Drawing.Size(60,30)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$Form.Close()})
    $form.Controls.Add($OKButton)

    #Add a cancel button
    $CancelButton = new-object System.Windows.Forms.Button
    $CancelButton.Location = new-object System.Drawing.Size(225,100)
    $CancelButton.Size = new-object System.Drawing.Size(60,30)
    $CancelButton.Text = "Cancel"
    $CancelButton.Margin = 0
    $CancelButton.Add_Click({$Form.Close()})
    $form.Controls.Add($CancelButton)

    $checkbox1.Add_CheckStateChanged({
        $results.one = $checkbox1.Checked
    })
    $checkbox2.Add_CheckStateChanged({
        $results.two = $checkbox2.Checked
    })


    # Activate the form
    $Form.Add_Shown({$Form.Activate()})
    [void] $Form.ShowDialog() 

$results
}
我不确定我引用结果哈希表的方式是否出错,或者整个方法是否都错了

编辑:我有一个想法,$year在事件处理程序中是没有意义的,所以我添加了

$checkbox.Name = $year
并将事件处理程序修改为

$results.($checkbox.Name) = $checkbox.Checked

但两人都不快乐。但奇怪的是,使用$self会导致在$return中添加一个奇怪的额外键。它没有键名,但该值与上次对任何复选框所做的更改相匹配

编辑#2:在进一步的测试中,我将处理程序更改为

$results.2019 = $checkbox.Checked
期望这意味着任何更改都会导致应用于2019密钥的更改。不是这样。所以我认为这与散列表的传递和引用方式有关,很可能我做的都是错的。也许令人担忧的是,我可以找到大量关于使复选框对表单的其他部分做出反应和更改的信息,但到目前为止,还没有找到任何关于返回结果的信息

编辑#3:好吧,答案似乎是(某种程度上)不需要事件处理程序,因为我只关心最终状态。所以,通过一些额外的清理来处理Cancel,我有了这个,它很有效。仍然很好奇我如何或者是否可以直接与事件处理程序中的$results交互

function checkbox_test{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

    $years = @('2016', '2017', '2018', '2019')
    $optionCount = $years.Count

    # Set the size of your form
    $Form = New-Object System.Windows.Forms.Form
    $form.FormBorderStyle = 'FixedDialog'
    $form.ShowInTaskbar = $false
    $Form.width = 300
    $Form.height = ($years.Count * 30 + 50 + 40) #150
    $Form.Text = ”Px Tools Updater”

    # 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

    # create Checkboxes
    $checkboxCount = 1
    foreach ($year in $years) {
        $checkbox = new-object System.Windows.Forms.checkbox
        $checkbox.Size = new-object System.Drawing.Size(100,20)
        $checkbox.Location  = new-object System.Drawing.Size(10,($checkbox.Size.Height*$checkboxCount-10))
        $checkbox.Text = "Revit $year"
        $checkbox.Name = $year
        $checkbox.Checked = $true
        $Form.Controls.Add($checkbox)
        $checkboxCount ++
    }

    # Add an OK button
    $OKButton = new-object System.Windows.Forms.Button
    $OKButton.Size = new-object System.Drawing.Size(60,30)
    $OKButton.Location = new-object System.Drawing.Size(10,($form.DisplayRectangle.Height - $OKButton.Size.Height - 10))
    $OKButton.Text = "OK"
    $OKButton.Add_Click({
        $Form.DialogResult = [System.Windows.Forms.DialogResult]::OK
        $Form.Close()
    })
    $form.Controls.Add($OKButton)

    #Add a cancel button
    $CancelButton = new-object System.Windows.Forms.Button
    $CancelButton.Size = new-object System.Drawing.Size(60,30)
    $CancelButton.Location = new-object System.Drawing.Size(($form.DisplayRectangle.Width - $CancelButton.Size.Width - 10),($form.DisplayRectangle.Height - $CancelButton.Size.Height - 10))
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({
        $Form.Close()
    })
    $form.Controls.Add($CancelButton)




    # Activate the form
    $Form.Add_Shown({$Form.Activate()})
    if ($Form.ShowDialog() -eq 'OK') {
        $results = New-Object Collections.Specialized.OrderedDictionary
        foreach ($control in $form.Controls) {
            if ($years -contains $control.Name) {
                $results.Add($control.Name, $control.Checked)
            }
        }
    } else {
        $results = $null
    }
    [void] $Form.Dispose

$results
}

#Call the function
$returned = checkbox_test

Foreach ($key in $returned.keys) {
    Write-Host "[$key] $($returned.$key)!"
}

用于分配上述每个复选框事件处理程序的
foreach
循环有效地覆盖了前一个复选框事件处理程序,因此只捕获最后一个复选框事件处理程序。(2019年)

相反,请指定事件处理程序:

$results.2019 = $checkbox.Checked
function checkbox_test{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

    $years = @('2016', '2017', '2018', '2019')
    $optionCount = $years.Count

    # Set the size of your form
    $Form = New-Object System.Windows.Forms.Form
    $form.FormBorderStyle = 'FixedDialog'
    $form.ShowInTaskbar = $false
    $Form.width = 300
    $Form.height = ($years.Count * 30 + 50 + 40) #150
    $Form.Text = ”Px Tools Updater”

    # 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

    # create Checkboxes
    $checkboxCount = 1
    foreach ($year in $years) {
        $checkbox = new-object System.Windows.Forms.checkbox
        $checkbox.Size = new-object System.Drawing.Size(100,20)
        $checkbox.Location  = new-object System.Drawing.Size(10,($checkbox.Size.Height*$checkboxCount-10))
        $checkbox.Text = "Revit $year"
        $checkbox.Name = $year
        $checkbox.Checked = $true
        $Form.Controls.Add($checkbox)
        $checkboxCount ++
    }

    # Add an OK button
    $OKButton = new-object System.Windows.Forms.Button
    $OKButton.Size = new-object System.Drawing.Size(60,30)
    $OKButton.Location = new-object System.Drawing.Size(10,($form.DisplayRectangle.Height - $OKButton.Size.Height - 10))
    $OKButton.Text = "OK"
    $OKButton.Add_Click({
        $Form.DialogResult = [System.Windows.Forms.DialogResult]::OK
        $Form.Close()
    })
    $form.Controls.Add($OKButton)

    #Add a cancel button
    $CancelButton = new-object System.Windows.Forms.Button
    $CancelButton.Size = new-object System.Drawing.Size(60,30)
    $CancelButton.Location = new-object System.Drawing.Size(($form.DisplayRectangle.Width - $CancelButton.Size.Width - 10),($form.DisplayRectangle.Height - $CancelButton.Size.Height - 10))
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({
        $Form.Close()
    })
    $form.Controls.Add($CancelButton)




    # Activate the form
    $Form.Add_Shown({$Form.Activate()})
    if ($Form.ShowDialog() -eq 'OK') {
        $results = New-Object Collections.Specialized.OrderedDictionary
        foreach ($control in $form.Controls) {
            if ($years -contains $control.Name) {
                $results.Add($control.Name, $control.Checked)
            }
        }
    } else {
        $results = $null
    }
    [void] $Form.Dispose

$results
}

#Call the function
$returned = checkbox_test

Foreach ($key in $returned.keys) {
    Write-Host "[$key] $($returned.$key)!"
}
$results = New-Object Collections.Specialized.OrderedDictionary;
foreach ($year in $years) {
    $checkbox = new-object System.Windows.Forms.checkbox
    $Form.Controls.Add($checkbox);
    $checkbox.Size = new-object System.Drawing.Size(100,20)
    $checkbox.Location  = new-object System.Drawing.Size(10,($checkbox.Size.Height*$checkboxCount-10))
    $checkbox.Text = "Revit $year"
    $checkbox.Name = $year
    $checkbox.Checked = $true
    $results.Add($year, $checkbox.Checked);
    # HERE!
    $checkbox.Add_CheckStateChanged({
        # $this -eq sender, optionally $_ -eq EventArgs
        $year = $this.name;
        $results.$year = $this.Checked;
    });      
    $checkboxCount++
}