允许在.NET TreeView中进行多选

我陷入了.NET 2.0 Windows窗体。

它看起来不像标准TreeView控件中存在选择多个节点的能力。

我正在尝试为上下文菜单选择执行此操作。 因此,复选框不是可接受的UI范例。

提供非常必要的function的最佳方法是什么?

我们曾在WTL项目中做过一次,但.NET所需的基本工作是相同的。 要实现多选树控制,您需要自己绘制树项并覆盖键盘和鼠标处理。 您还需要维护自己选择的项目列表。

不要忘记考虑选择规则(例如,允许父母和孩子),并且不要忘记实现键盘快捷键,包括使用Ctrl,Shift和Ctrl + Shift选择,以及用于选择/取消选择的空格键。

TreeView.CheckBoxes

复选框是一个选项吗? 或者你想要一个列表框中的选择?

  • 复选框是内置的
  • 选择就像你进入列表框需要自定义树控件

CodeProject上有一个多选树控件: 多选树视图

您可以查看第三方解决方案。 Infragistics树就是这样做的。 不是免费的,但是寻找解决方案所花费的时间也不是免费的。

下面的代码将允许您调整您使用的背景颜色,以确保突出显示所有选定的节点。

 protected override void WndProc(ref Message m) { switch (m.Msg) { // WM_REFLECT is added because WM_NOTIFY is normally sent just // to the parent window, but Windows.Form will reflect it back // to us, MFC-style. case Win32.WM_REFLECT + Win32.WM_NOTIFY: { Win32.NMHDR nmhdr = (Win32.NMHDR)m.GetLParam(typeof(Win32.NMHDR)); switch((int)nmhdr.code) { case Win32.NM_CUSTOMDRAW: base.WndProc(ref m); Win32.NMTVCUSTOMDRAW nmTvDraw = (Win32.NMTVCUSTOMDRAW)m.GetLParam(typeof(Win32.NMTVCUSTOMDRAW)); switch (nmTvDraw.nmcd.dwDrawStage) { case Win32.CDDS_ITEMPREPAINT: // Find the node being painted. TreeNode n = TreeNode.FromHandle(this, nmTvDraw.nmcd.lItemlParam); if (allSelected.Contains(n)) // Override its background colour. nmTvDraw.clrTextBk = ColorTranslator.ToWin32(SystemColors.Highlight); m.Result = (IntPtr)Win32.CDRF_DODEFAULT; // Continue rest of painting as normal break; } Marshal.StructureToPtr(nmTvDraw, m.LParam, false); // copy changes back return; } break; } } base.WndProc(ref m); } // WM_NOTIFY notification message header. [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] public class NMHDR { private IntPtr hwndFrom; public IntPtr idFrom; public uint code; } [StructLayout(LayoutKind.Sequential)] public struct NMCUSTOMDRAW { public NMHDR hdr; public int dwDrawStage; public IntPtr hdc; public RECT rc; public IntPtr dwItemSpec; public int uItemState; public IntPtr lItemlParam; } [StructLayout(LayoutKind.Sequential)] public struct NMTVCUSTOMDRAW { public NMCUSTOMDRAW nmcd; public int clrText; public int clrTextBk; public int iLevel; } public const int CDIS_SELECTED = 0x0001; public const int CDIS_FOCUS = 0x0010; public const int CDDS_PREPAINT = 0x00000001; public const int CDDS_POSTPAINT = 0x00000002; public const int CDDS_PREERASE = 0x00000003; public const int CDDS_POSTERASE = 0x00000004; public const int CDDS_ITEM = 0x00010000; // item specific public const int CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT); public const int CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT); public const int CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE); public const int CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE); public const int CDDS_SUBITEM = 0x00020000; public const int CDRF_DODEFAULT = 0x00000000; public const int CDRF_NOTIFYITEMDRAW = 0x00000020; public const int CDRF_NOTIFYSUBITEMDRAW = 0x00000020; // flags are the same, we can distinguish by context public const int WM_USER = 0x0400; public const int WM_NOTIFY = 0x4E; public const int WM_REFLECT = WM_USER + 0x1C00; 

最简单的解决方案是扩展框架附带的现有TreeView控件,并使用逻辑覆盖OnBeforeSelect和OnAfterSelect方法以捕获多个选择。

可以在此处找到一个示例: http : //www.arstdesign.com/articles/treeviewms.html