在多个复选框上构建并响应事件

时间:2018-06-21 19:18:30

标签: winforms powershell

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

    $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.Checked = $true
        $Form.Controls.Add($checkbox)
        $checkbox.Add_CheckStateChanged({
            $results.$year = $checkbox.Checked
        })
        $checkboxCount ++
    }

和正确创建了复选框,但是当我从函数返回$results时,它们都为True。我以此为基础建立了代码,该代码可以正常工作,但是具有固定数量的复选框。

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

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

但是两者都不高兴。但是奇怪的是,使用$ self会导致将一个奇怪的额外键添加到$ return中。它没有键名,但该值与对任何复选框所做的最后更改相匹配。

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

$results.2019 = $checkbox.Checked

期望表示任何更改都会导致将更改应用到2019年密钥。不是。因此,我认为这与哈希表的传递和引用方式有关,很可能我做错了。也许令人担忧的事实是,我可以在使复选框做出反应并更改表格的其他部分时发现大量信息,但到目前为止,仅获得结果就什么也没有。

编辑#3:好的,似乎(某种程度上)答案是不需要事件处理程序,因为无论如何我实际上只关心结束状态。因此,通过进行一些额外的清理以处理“取消”,我有了它,并且它可以正常工作。仍然好奇我如何或者是否可以直接与事件处理程序中的$ 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)!"
}

1 个答案:

答案 0 :(得分:0)

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

相反,分配事件处理程序the way it's traditionally done in Windows Forms

$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++
}