PowerShell WinForms:事件块内ListBox的SelectedItems值获取方法
问题:WinForms ListBox选中项无法获取,始终为Null
从下拉列表$RCVROption选择选项后,再选择$listBox中的选项,$listBox.SelectedItems的值始终为Null,如何获取该值并赋值给变量$x?
目标是将$listBox.SelectedItems的文本作为文件名,选中列表选项并点击OK后运行对应文件。尝试的脚本如下:
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing [System.Windows.Forms.Application]::EnableVisualStyles() $form = New-Object System.Windows.Forms.Form $form.Text = 'DMP Receiver Tail' $form.Size = New-Object System.Drawing.Size(400,300) $form.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(115,220) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(190,220) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Cancel' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(60,20) $label.Size = New-Object System.Drawing.Size(280,20) $label.Text = 'Which Receiver Would You Like To Tail?:' $form.Controls.Add($label) $RCVROption = new-object System.Windows.Forms.combobox $RCVROption.Location = new-object System.Drawing.Size(20,40) $RCVROption.Size = new-object System.Drawing.Size(335,30) [void] $RCVROption.Items.Add('Receiver 560') [void] $RCVROption.Items.Add('Receiver 2560') $RCVROption.tabIndex = '0' $RCVROption.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList; $RCVROption.add_SelectedValueChanged( { if($RCVROption.SelectedItem -eq 'Receiver 560') { $listBox = New-Object System.Windows.Forms.Listbox $listBox.Location = New-Object System.Drawing.Point(40,100) $listBox.Size = New-Object System.Drawing.Size(260,80) $listBox.SelectionMode = 'MultiExtended' [void] $listBox.Items.Add('DMP-560-Line1') [void] $listBox.Items.Add('DMP-560-Line2') [void] $listBox.Items.Add('DMP-560-Line3') [void] $listBox.Items.Add('DMP-560-Line4') [void] $listBox.Items.Add('DMP-560-Line5') $form.Controls.Add($listBox) } ELSEIF($RCVROption.SelectedItem -eq 'Receiver 2560') { $listBox = New-Object System.Windows.Forms.Listbox $listBox.Location = New-Object System.Drawing.Point(40,100) $listBox.Size = New-Object System.Drawing.Size(260,80) $listBox.SelectionMode = 'MultiExtended' [void] $listBox.Items.Add('DMP-2560-Line1') [void] $listBox.Items.Add('DMP-2560-Line2') [void] $listBox.Items.Add('DMP-2560-Line3') [void] $listBox.Items.Add('DMP-2560-Line4') [void] $listBox.Items.Add('DMP-2560-Line5') $form.Controls.Add($listBox) } } ) $form.Controls.Add($RCVROption) $form.Topmost = $true $result = $form.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $x = $listBox.SelectedItems $Fpath = 'D:\Toolbar\On Call\DMP-Tail\' + $x + '.exe' Start-process -filepath $FPath $Fpath }
问题根源
- 作用域限制:事件脚本块内创建的
$listBox是局部变量,外部的OK按钮逻辑无法访问该变量,导致$listBox在OK块中为Null。 - 重复创建控件:每次切换ComboBox选项都会新建ListBox并添加到窗体,造成控件叠加,且只有最后创建的ListBox在局部作用域中,进一步引发变量访问问题。
修复方案与修正代码
- 提前声明脚本级ListBox:在事件外部创建ListBox并添加到窗体,确保变量在整个脚本作用域中可访问。
- 动态更新ListBox内容:切换ComboBox选项时清空现有项并添加对应内容,避免重复创建控件。
- 处理多选场景:由于ListBox设置了
MultiExtended多选模式,需遍历选中项逐个启动程序。
修正后的脚本:
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing [System.Windows.Forms.Application]::EnableVisualStyles() $form = New-Object System.Windows.Forms.Form $form.Text = 'DMP Receiver Tail' $form.Size = New-Object System.Drawing.Size(400,300) $form.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(115,220) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(190,220) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Cancel' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(60,20) $label.Size = New-Object System.Drawing.Size(280,20) $label.Text = 'Which Receiver Would You Like To Tail?:' $form.Controls.Add($label) $RCVROption = New-Object System.Windows.Forms.ComboBox $RCVROption.Location = New-Object System.Drawing.Size(20,40) $RCVROption.Size = New-Object System.Drawing.Size(335,30) [void]$RCVROption.Items.Add('Receiver 560') [void]$RCVROption.Items.Add('Receiver 2560') $RCVROption.TabIndex = 0 $RCVROption.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList # 提前创建ListBox并添加到窗体,脚本级变量全局可访问 $listBox = New-Object System.Windows.Forms.ListBox $listBox.Location = New-Object System.Drawing.Point(40,100) $listBox.Size = New-Object System.Drawing.Size(260,80) $listBox.SelectionMode = 'MultiExtended' $form.Controls.Add($listBox) $RCVROption.add_SelectedValueChanged({ $listBox.Items.Clear() # 清空现有项 switch ($RCVROption.SelectedItem) { 'Receiver 560' { [void]$listBox.Items.Add('DMP-560-Line1') [void]$listBox.Items.Add('DMP-560-Line2') [void]$listBox.Items.Add('DMP-560-Line3') [void]$listBox.Items.Add('DMP-560-Line4') [void]$listBox.Items.Add('DMP-560-Line5') } 'Receiver 2560' { [void]$listBox.Items.Add('DMP-2560-Line1') [void]$listBox.Items.Add('DMP-2560-Line2') [void]$listBox.Items.Add('DMP-2560-Line3') [void]$listBox.Items.Add('DMP-2560-Line4') [void]$listBox.Items.Add('DMP-2560-Line5') } } }) $form.Controls.Add($RCVROption) $form.Topmost = $true $result = $form.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { # 遍历所有选中项,逐个启动对应程序 foreach ($selectedItem in $listBox.SelectedItems) { $Fpath = "D:\Toolbar\On Call\DMP-Tail\$selectedItem.exe" Start-Process -FilePath $FPath Write-Host "已启动程序: $Fpath" } }
内容的提问来源于stack exchange,提问作者Zagnut119
相关产品推荐
相关产品推荐

