“按引用传递”似乎有效,但仍会生成错误?如何从WinForms对话框返回多个值?

“按引用传递”似乎有效,但仍会生成错误?如何从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){

背景

我正在尝试制作一个WinForm,当用户点击“提交”按钮时,提交函数中的所有值都返回到要处理的main。出于测试目的,我刚刚尝试让
$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
  • PowerShell在运行时传递/分配变量时出现问题
  • 我的脚本有问题(我不习惯先定义函数)

  • 回答:脚本组件出现故障

    需要:

    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单击({…})
        时所做的那样

      • 警告:脚本块在子变量作用域中运行,因此需要额外的工作来修改调用方作用域中的变量,例如使用
        script
        作用域说明符;e、 例如,
        $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
    开始的,但调用函数时它似乎只返回值,而不是实际的变量。其他人似乎都认为,让它全球化或成为一个对象才是出路。搜索引擎在寻找好的阅读材料方面非常有用。还有一些书。正如你所注意到的,事情“不起作用”是令人沮丧的,但这是由于根本的误解。你需要先学会走路,然后才能跑。