【问题标题】:Using form to return variable fails to produce a return value使用表单返回变量无法产生返回值
【发布时间】:2016-09-02 06:42:05
【问题描述】:

我正在为用户编写一个脚本,该脚本连接多个 PDF 文件并将表格数据附加为文本文件。现在的问题是用户可以手动命名文本文件,以便脚本必须验证哪个 PDF 文件属于数据。通常它会按名称这样做,但由于用户可以(并且显然会)更改 PDF 的名称,脚本会要求用户选择正确的 PDF 进行合并。

我在我的脚本中编写了一个函数,它使用 Winforms 显示一个包含可用 PDF 文件的列表框,用户应该选择一个。

function Select-Rechnung
{
    param
    (
        [string] $Rechnung,
        [string[]] $PdfFiles
    )

    $form = New-Object System.Windows.Forms.Form
    $form.Text = "Rechnung wählen"
    $form.Size = New-Object System.Drawing.Size(640,320)
    $form.StartPosition = "CenterScreen"

    $form.KeyPreview = $true
    $form.Add_KeyDown({if($_.KeyCode -eq "Enter") { $x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() }})
    $form.Add_KeyDown({if($_.KeyCode -eq "Escape") { $form.Close() }})

    $OkButton = New-Object System.Windows.Forms.Button
    $OkButton.Location = New-Object System.Drawing.Size(240,240)
    $OkButton.Size = New-Object System.Drawing.Size(75,23)
    $OkButton.Text = "OK"
    $OkButton.Add_Click({ $x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() })
    $form.Controls.Add($OkButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(325,240)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Abbrechen"
    $CancelButton.Add_Click({$form.Close()})
    $form.Controls.Add($CancelButton)

    $Label = New-Object System.Windows.Forms.Label
    $Label.Location = New-Object System.Drawing.Size(10,20) 
    $Label.Size = New-Object System.Drawing.Size(600,20) 
    $Label.Text = [string]::Format("Für die Rechnung {0} wurden mehrere mögliche Dateien gefunden. Bitte auswählen:", $Rechnung)
    $form.Controls.Add($Label)

    $ListBox = New-Object System.Windows.Forms.ListBox
    $ListBox.Location = New-Object System.Drawing.Size(10,40)
    $ListBox.Size = New-Object System.Drawing.Size(600, 20)
    $ListBox.Height = 200
    foreach($pdfFile in $PdfFiles)
    {
        [void] $ListBox.Items.Add($pdfFile)
    }
    $form.Controls.Add($ListBox)

    $form.TopMost = $true
    $form.Add_Shown({$form.Activate()})
    [void] $form.ShowDialog()

    $x
}

现在在KeyDown 处理程序或Click 处理程序内,该函数应将选定的PDF 文件分配给变量$x。我检查了 $PdfFiles 是否正确地传递给函数,并且在处理程序执行期间,$PdfFiles[$ListBox.SelectedIndex] 实际上具有正确的字符串值。但是,当我在处理完表单ShowDialog 后访问$x 时,它是空的,因此函数的返回值是空的。

为什么它不将值(它在处理程序期间正确评估)分配给我的变量并返回它?

【问题讨论】:

    标签: .net winforms powershell


    【解决方案1】:

    通过引入像哈希表这样的引用类型来尝试它,并使用它来修改和返回值,像这样

    function Select-Rechnung
    {
        param
        (
            [string] $Rechnung,
            [string[]] $PdfFiles
        )
    
        $x = @{ Value = '' }
    
        ...
        $OkButton.Add_Click({ $x.Value = $PdfFiles[$ListBox.SelectedIndex];
        ...
    
        $x.Value
    }
    

    你也可以通过使用Set-Variable -Name x -Scope 1 $PdfFiles[$ListBox.SelectedIndex]访问外部作用域的$x变量来实现你的目标
    或其他范围修饰符之一(globalscript - 请参阅 about scopes),如果您想避免额外的哈希表。

    【讨论】:

      【解决方案2】:

      我建议您将 $x 变量的作用域级别至少更改为 脚本作用域,这样它就可以在脚本中的任何地方使用。现在它只是“生活”在句柄事件的脚本块中。将每个 $x 变量更改为 $script:x

      function Select-Rechnung
      {
          param
          (
              [string] $Rechnung,
              [string[]] $PdfFiles
          )
      
          $form = New-Object System.Windows.Forms.Form
          $form.Text = "Rechnung wählen"
          $form.Size = New-Object System.Drawing.Size(640,320)
          $form.StartPosition = "CenterScreen"
      
          $form.KeyPreview = $true
          $form.Add_KeyDown({if($_.KeyCode -eq "Enter") { $script:x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() }})
          $form.Add_KeyDown({if($_.KeyCode -eq "Escape") { $form.Close() }})
      
          $OkButton = New-Object System.Windows.Forms.Button
          $OkButton.Location = New-Object System.Drawing.Size(240,240)
          $OkButton.Size = New-Object System.Drawing.Size(75,23)
          $OkButton.Text = "OK"
          $OkButton.Add_Click({ $script:x = $PdfFiles[$ListBox.SelectedIndex]; $form.Close() })
          $form.Controls.Add($OkButton)
      
          $CancelButton = New-Object System.Windows.Forms.Button
          $CancelButton.Location = New-Object System.Drawing.Size(325,240)
          $CancelButton.Size = New-Object System.Drawing.Size(75,23)
          $CancelButton.Text = "Abbrechen"
          $CancelButton.Add_Click({$form.Close()})
          $form.Controls.Add($CancelButton)
      
          $Label = New-Object System.Windows.Forms.Label
          $Label.Location = New-Object System.Drawing.Size(10,20) 
          $Label.Size = New-Object System.Drawing.Size(600,20) 
          $Label.Text = [string]::Format("Für die Rechnung {0} wurden mehrere mögliche Dateien gefunden. Bitte auswählen:", $Rechnung)
          $form.Controls.Add($Label)
      
          $ListBox = New-Object System.Windows.Forms.ListBox
          $ListBox.Location = New-Object System.Drawing.Size(10,40)
          $ListBox.Size = New-Object System.Drawing.Size(600, 20)
          $ListBox.Height = 200
          foreach($pdfFile in $PdfFiles)
          {
              [void] $ListBox.Items.Add($pdfFile)
          }
          $form.Controls.Add($ListBox)
      
          $form.TopMost = $true
          $form.Add_Shown({$form.Activate()})
          [void] $form.ShowDialog()
      
          $script:x
      }
      

      它现在对我有用:

      Select-Rechnung -Rechnung 'string' -PdfFiles 'file1.pdf','file2.pdf','file3.pdf'
      

      输出:

      file3.pdf
      

      【讨论】:

        【解决方案3】:

        我现在通过解决这个问题做到了。在KeyDownClick 处理程序中,我不再直接设置变量,而是:

        $form.Add_KeyDown({
            if($_.KeyCode -eq "Enter") 
            { 
                 if($ListBox.SelectedIndex -ge 0) 
                 { 
                     $form.DialogResult = System.Windows.Forms.DialogResult]::OK;
                 } 
                 $form.Close() 
            }
        })
        

        最后我确实检查了DialogResult

        [string]$x = $null
        if($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK)
        {
            $x = $PdfFiles[$ListBox.SelectedIndex]
        }   
        return $x
        

        这确实导致返回正确的值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-02-25
          • 2013-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多