PowerShell WinForms:如何用C#扩展命名空间实现ListView组可折叠
实现WinForms ListView组可折叠的PowerShell方案
要让ListView组支持折叠,你需要通过自定义C#扩展逻辑拦截组标题的点击事件,再控制组内项的可见性。以下是完整的可运行步骤和代码:
1. 加载自定义ListView扩展类
先用Add-Type加载包含扩展逻辑的C#代码,这段代码会给ListView添加组点击事件的处理能力:
Add-Type @" using System; using System.Windows.Forms; using System.Runtime.InteropServices; public class ListViewGroupCollapseExtension { private const int WM_LBUTTONDOWN = 0x0201; private const int LVM_SUBITEMHITTEST = 0x1039; [StructLayout(LayoutKind.Sequential)] private struct LVHITTESTINFO { public Point pt; public int flags; public int iItem; public int iSubItem; public int iGroup; } private ListView _listView; public ListViewGroupCollapseExtension(ListView listView) { _listView = listView; _listView.MouseDown += ListView_MouseDown; } private void ListView_MouseDown(object sender, MouseEventArgs e) { var hitTestInfo = new LVHITTESTINFO(); hitTestInfo.pt = e.Location; var result = SendMessage(_listView.Handle, LVM_SUBITEMHITTEST, IntPtr.Zero, ref hitTestInfo); if ((hitTestInfo.flags & 0x100) != 0) { var group = _listView.Groups[hitTestInfo.iGroup]; ToggleGroupCollapse(group); } } private void ToggleGroupCollapse(ListViewGroup group) { bool isCollapsed = false; if (group.Items.Count > 0) { isCollapsed = !group.Items[0].Visible; } foreach (ListViewItem item in group.Items) { item.Visible = isCollapsed; } group.Header = isCollapsed ? group.Header.Replace(" [-]", " [+]") : group.Header.Replace(" [+]", " [-]"); } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, ref LVHITTESTINFO lp); } "@ -ReferencedAssemblies System.Windows.Forms, System.Drawing
2. 创建窗体并初始化ListView
在窗体代码中,实例化ListView后,创建ListViewGroupCollapseExtension对象绑定到ListView上,即可启用折叠功能:
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object System.Windows.Forms.Form $form.Text = "可折叠ListView组演示" $form.Size = New-Object System.Drawing.Size(600, 400) $listView = New-Object System.Windows.Forms.ListView $listView.Dock = [System.Windows.Forms.DockStyle]::Fill $listView.View = [System.Windows.Forms.View]::Details $listView.ShowGroups = $true # 添加列 $listView.Columns.Add("名称", 200) | Out-Null $listView.Columns.Add("类型", 150) | Out-Null $listView.Columns.Add("大小", 100) | Out-Null # 创建测试组和项 $group1 = New-Object System.Windows.Forms.ListViewGroup("文档 [-]", [System.Windows.Forms.HorizontalAlignment]::Left) $group1.Items.Add((New-Object System.Windows.Forms.ListViewItem("报告.docx"))) | Out-Null $group1.Items.Add((New-Object System.Windows.Forms.ListViewItem("表格.xlsx"))) | Out-Null $group2 = New-Object System.Windows.Forms.ListViewGroup("图片 [-]", [System.Windows.Forms.HorizontalAlignment]::Left) $group2.Items.Add((New-Object System.Windows.Forms.ListViewItem("风景.jpg"))) | Out-Null $group2.Items.Add((New-Object System.Windows.Forms.ListViewItem("头像.png"))) | Out-Null $listView.Groups.Add($group1) | Out-Null $listView.Groups.Add($group2) | Out-Null # 绑定折叠扩展 $collapseExtension = New-Object ListViewGroupCollapseExtension($listView) $form.Controls.Add($listView) $form.ShowDialog() | Out-Null
关键说明
- 扩展类通过拦截
WM_LBUTTONDOWN消息,调用LVM_SUBITEMHITTEST判断点击位置是否在组标题上 - 点击组标题时,切换组内所有项的
Visible属性,同时更新组标题文本显示折叠/展开状态([+]为折叠,[-]为展开) - 初始化组标题时需包含
[-],保证切换时能正确替换状态标识
内容的提问来源于stack exchange,提问作者Scepticalist
相关产品推荐
相关产品推荐

