“按引用传递”似乎有效,但仍会生成错误?如何从WinForms对话框返回多个值?
背景 我正在尝试制作一个WinForm,当用户点击“提交”按钮时,提交函数中的所有值都返回到要处理的main。出于测试目的,我刚刚尝试让“按引用传递”似乎有效,但仍会生成错误?如何从WinForms对话框返回多个值?,winforms,function,powershell,parameter-passing,pass-by-reference,Winforms,Function,Powershell,Parameter Passing,Pass By Reference,背景 我正在尝试制作一个WinForm,当用户点击“提交”按钮时,提交函数中的所有值都返回到要处理的main。出于测试目的,我刚刚尝试让$firstName工作。为了做到这一点,我一直在试图找出通过引用传递的参数 此代码块自身工作: $txtFirstName = New-Object system.Windows.Forms.TextBox $txtFirstName.text = "John" function Submit([ref]$firstName){
$firstName
工作。为了做到这一点,我一直在试图找出通过引用传递的参数
此代码块自身工作:
$txtFirstName = New-Object system.Windows.Forms.TextBox
$txtFirstName.text = "John"
function Submit([ref]$firstName){
$firstName.value = $txtFirstName.Text
}
$firstName = $null
Submit([ref]$firstName)
$firstName
然而,当我尝试将相同的概念应用到我的应用程序时,它似乎起了作用,但是我仍然得到了一个错误
错误:
$txtFirstName = New-Object system.Windows.Forms.TextBox
$txtFirstName.text = "John"
function Submit([ref]$firstName){
$firstName.value = $txtFirstName.Text
}
$firstName = $null
Submit([ref]$firstName)
$firstName
在此对象上找不到属性“value”;确保它存在并且可设置
这是我的剧本:
我的假设:
$txtFirstName = New-Object system.Windows.Forms.TextBox
$txtFirstName.text = "John"
function Submit([ref]$firstName){
$firstName.value = $txtFirstName.Text
}
$firstName = $null
Submit([ref]$firstName)
$firstName
回答:脚本组件出现故障 需要:
function Submit(){...}
<form fields>
[void]$NewUserForm.ShowDialog()
Submit([ref]$firstName)
$btnSubmit.Add_Click({ Submit }) #GUI event
$firstName
函数Submit(){…}
[void]$NewUserForm.ShowDialog()
提交([ref]$firstName)
$btnSubmit.Add_Click({Submit})#GUI事件
$firstName
而不是:
function Submit(){...}
<form fields>
$btnSubmit.Add_Click({ Submit }) #GUI event
[void]$NewUserForm.ShowDialog()
Submit([ref]$firstName)
$firstName
函数Submit(){…}
$btnSubmit.Add_Click({Submit})#GUI事件
[void]$NewUserForm.ShowDialog()
提交([ref]$firstName)
$firstName
如果有人链接到我可以了解更多关于如何订购脚本和方法的信息,我将不胜感激 中介绍了原始代码段工作的原因以及链接的完整脚本不工作的原因 简而言之:您有一个事件处理程序,该处理程序首先调用了
Submit
函数,但没有参数,后来又使用参数正确地调用了该函数,这导致了问题
关于中的解释: 您重新排列的代码只会意外工作: 在显示对话框后,它附加了包含有缺陷的、无参数的
Submit
调用的事件处理程序,此时它什么也不做
如何构造代码:
$txtFirstName = New-Object system.Windows.Forms.TextBox
$txtFirstName.text = "John"
function Submit([ref]$firstName){
$firstName.value = $txtFirstName.Text
}
$firstName = $null
Submit([ref]$firstName)
$firstName
您有两个基本选项,它们通常组合在一起:
- 在显示对话框时使用事件处理程序执行操作
- 您可以将事件处理程序作为传递给各个控件的脚本块附加到“
方法,就像您在.Add()
时所做的那样$btnSubmit.Add\u单击({…})
- 警告:脚本块在子变量作用域中运行,因此需要额外的工作来修改调用方作用域中的变量,例如使用
作用域说明符;e、 例如,script
(甚至可以使用$script:var
方法,但这是一种高压方法)[ref]
- 您可以将事件处理程序作为传递给各个控件的脚本块附加到“
- 在对话框关闭后执行操作
- 然后,您可以直接访问表单控件的属性
Add-Type -AssemblyName System.Windows.Forms
# Create the form.
$form = New-Object system.Windows.Forms.Form -Property @{
ClientSize = New-Object System.Drawing.Point 400,100
Text = "Dialog Demo"
}
# Create the controls and add them to the form.
$form.Controls.AddRange(@(
New-Object system.Windows.Forms.Label -Property @{
Text = "First Name:"
AutoSize = $true
Location = New-Object System.Drawing.Point 10,20
Font = 'Microsoft Sans Serif,10'
}
($txtFirstName = New-Object system.Windows.Forms.TextBox -Property @{
Width = 250
Location = New-Object System.Drawing.Point 100, 20
})
($btnSubmit = New-Object system.Windows.Forms.Button -Property @{
Text = "Submit"
Location = New-Object System.Drawing.Point 160, 60
})
))
# Attach an event handler to the first-name field.
$txtFirstName.Add_KeyPress({ param($obj, $evArgs)
# Example: Convert every character typed to uppercase.
$evArgs.KeyChar = [char]::ToUpper($evArgs.KeyChar)
})
# Make pressing Enter the same as clicking the Submit button.
$form.AcceptButton = $btnSubmit
# Make the Submit button act like an OK button, which means:
# - auto-close the form
# - make .ShowDialog() return [System.Windows.Forms.DialogResult]::OK
$btnSubmit.DialogResult = [System.Windows.Forms.DialogResult]::OK
# Show the form synchronously (during which event handlers may fire)
# and take action based on the return value, which is
# a [System.Windows.Forms.DialogResult] enumeration value that
# reflects the button used to close the form.
if ($form.ShowDialog() -eq 'OK') { # Dialog was confirmed.
# You can now access the controls' properties as needed.
# In this example we output a custom object that contains
# the first name; this can easily be extended to include
# other properties
[pscustomobject] @{
FirstName = $txtFirstName.Text
}
} else { # Dialog was canceled.
Write-Warning "Dialog canceled."
}
为什么你需要通过参考传递?函数输出值。我返回一组字符串。我已经编程多年了,但这就是我记得C++中的事情。如果您查看我的代码,我基本上希望在点击提交按钮后,文本字段中的所有信息等都将分配给一个变量。这样,在main和其他函数中,我可以直接引用
$FirstName
,而不是txtFirstName.text
。我已经提出了其他方法来实现这一点,人们建议分配对象或使其全球化,但这是我最熟悉的,我在这方面取得了一些成功,但并不完全了解其他方法。我认为您需要了解更多有关PowerShell如何工作的信息。PowerShell函数可以返回(输出)字符串列表。是的,我可以。阅读材料会很好。我最初是从return$firstname
开始的,但调用函数时它似乎只返回值,而不是实际的变量。其他人似乎都认为,让它全球化或成为一个对象才是出路。搜索引擎在寻找好的阅读材料方面非常有用。还有一些书。正如你所注意到的,事情“不起作用”是令人沮丧的,但这是由于根本的误解。你需要先学会走路,然后才能跑。