You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell GUI开发:如何通过下拉列表选中项填充Listbox

Active Directory应用部署工具:下拉列表选中项添加到ListBox的问题解决

问题分析

原代码存在以下核心问题:

  • 每次下拉框选中索引变化时,都会重新创建ListBox控件,导致旧控件被覆盖、之前添加的内容丢失,且无法正常进行选中操作。
  • GetApplicationDetails函数错误地给ListBox绑定了点击事件,逻辑完全偏离需求——需求是选中下拉框项后添加到ListBox,而非点击ListBox时触发添加。
  • 变量作用域错误,ListBox应在表单初始化阶段创建并添加到表单,而非事件触发时动态生成。
  • 事件处理逻辑引用了不存在的变量($_appddl.Appname、$SelectedItems),导致无法正确传递选中项。

修正后的完整代码

Add-Type -AssemblyName System.Windows.Forms
Import-Module ActiveDirectory

# 初始化表单及控件类型
$FormObject = [System.Windows.Forms.Form]
$LabelObject = [System.Windows.Forms.Label]
$ComboBoxObject = [System.Windows.Forms.ComboBox]
$ListBoxObject = [System.Windows.Forms.Listbox]

# 主窗口配置
$AppForm = New-Object $FormObject 
$AppForm.ClientSize = '1500,1000'
$AppForm.Text = 'Search and Deploy Application'
$AppForm.BackColor = 'White'
$AppForm.Font = [System.Drawing.Font]::new("Verdana", 10)

# 应用标签
$AppLabel = New-Object $LabelObject
$AppLabel.Text = 'Applications :'
$AppLabel.AutoSize = $true 
$AppLabel.Location = New-Object System.Drawing.Point(100, 202)

# 已选应用标签
$StdAppLabel = New-Object $LabelObject
$StdAppLabel.Text = 'Selected Applications : '
$StdAppLabel.AutoSize = $true 
$StdAppLabel.Location = New-Object System.Drawing.Point(100, 262)

# 选中应用名称标签(可选保留)
$StdAppName = New-Object $LabelObject
$StdAppName.Text = 'Text'
$StdAppName.AutoSize = $true
$StdAppName.Location = New-Object System.Drawing.Point(225, 262)

# 应用下拉框
$appddl = New-Object $ComboBoxObject
$appddl.Width = 520
$appddl.Font = [System.Drawing.Font]::new("Verdana", 10)
$appddl.Location = New-Object System.Drawing.Point(180, 195)
$appddl.AutoCompleteSource = 'ListItems'
$appddl.AutoCompleteMode = 'Suggest'

# 已选应用ListBox(初始化时创建,而非事件触发时)
$ApplistBox = New-Object $ListBoxObject
$ApplistBox.Location = New-Object System.Drawing.Point(222, 257)
$ApplistBox.Width = 480
$ApplistBox.SelectionMode = 'MultiExtended'
$ApplistBox.Height = 300

# 加载AD应用到下拉框
function Load-Combobox-Apps {
    $appddl.Items.Clear()
    # 从AD获取应用组并提取名称
    $apparray = Get-ADGroup -Filter { Name -like "AP_SCCM_FBC_*" } | 
                Select-Object Name, @{Name = 'Appname'; Expression = { $_.Name -replace 'AP_SCCM_FBC_', '' } }
    
    foreach ($Item in $apparray) {
        $appddl.Items.Add($Item.Appname)
    }
}

# 下拉框选中事件:添加选中项到ListBox(避免重复添加)
$appddl.Add_SelectedIndexChanged({
    $selectedApp = $appddl.SelectedItem
    # 检查ListBox中是否已存在该应用,避免重复添加
    if ($selectedApp -and $ApplistBox.Items.Contains($selectedApp) -eq $false) {
        $ApplistBox.Items.Add($selectedApp)
        # 更新选中应用名称标签(可选)
        $StdAppName.Text = $selectedApp
    }
})

# 添加删除选中项的功能(满足需求中的可删除选中项)
$removeBtn = New-Object System.Windows.Forms.Button
$removeBtn.Text = "Remove Selected"
$removeBtn.Location = New-Object System.Drawing.Point(710, 257)
$removeBtn.Width = 120
$removeBtn.Add_Click({
    # 反向遍历选中项,避免索引错乱
    for ($i = $ApplistBox.SelectedIndices.Count - 1; $i -ge 0; $i--) {
        $ApplistBox.Items.RemoveAt($ApplistBox.SelectedIndices[$i])
    }
})

# 加载应用到下拉框
Load-Combobox-Apps

# 将所有控件添加到表单
$AppForm.Controls.AddRange(@(
    $AppLabel, $appddl, $StdAppLabel, $StdAppName, 
    $ApplistBox, $removeBtn
))

# 显示表单
$AppForm.ShowDialog()
$AppForm.Dispose()

关键修改说明

  • ListBox初始化时机调整:在表单初始化阶段就创建ListBox并添加到表单,避免每次下拉框选中时重复生成控件。
  • 修正下拉框事件逻辑:直接在Add_SelectedIndexChanged事件中获取下拉框选中项,检查是否已存在于ListBox后添加,避免重复项。
  • 新增删除功能:添加删除按钮,实现多选删除需求,通过反向遍历选中索引避免删除时出现索引错乱。
  • 优化AD数据提取:用-replace替代-split/-join,更简洁地提取应用名称。
  • 调整自动补全配置:将自动补全的设置移到循环外,无需每次添加项时重复配置。

内容的提问来源于stack exchange,提问作者KiloByte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:37:01