带复选框的TreeView
项目中多处用到TreeView,每一个树都要全选、取消全选、层级联动、屏蔽双击复选框,于是很有必要封装一个CheckTreeView,步骤如下:
- 在项目中右键->添加->新建项,选择Windows Forms下的用户控件,名称改为CheckTreeView.cs
- 拖入一个TreeView,CheckBoxes属性改为True,Dock属性改为Fill
- 拖入一个contextMenuStrip,添加子项“全选”和“全不选”,并双击子项生成事件处理函数
- 将treeView1的ContextMenuStrip属性改为contextMenuStrip1
- 编写如下代码,然后在CheckTreeView.Designer.cs中,将treeView1的类型改为TreeViewEnhanced
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace MyControls
{
public partial class CheckTreeView : UserControl
{
bool _isEnglish = false;
public CheckTreeView()
{
InitializeComponent();
treeView1.CheckBoxes = true;
}
public bool IsEnglish
{
get
{
return _isEnglish;
}
set
{
_isEnglish = value;
if (_isEnglish)
{
contextMenuStrip1.Items[0].Text = "CheckAll";
contextMenuStrip1.Items[1].Text = "CheckNone";
}
else
{
contextMenuStrip1.Items[0].Text = "全选";
contextMenuStrip1.Items[1].Text = "全不选";
}
}
}
public TreeView TreeView { get { return treeView1; } }
/// <summary>
/// 全选
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menu_CheckNone_Click(object sender, EventArgs e)
{
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = false;
setChildNodeCheckedState(node, false);
}
}
/// <summary>
/// 全部不选
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menu_CheckAll_Click(object sender, EventArgs e)
{
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = true;
setChildNodeCheckedState(node, true);
}
}
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action == TreeViewAction.ByMouse)
{
if (e.Node.Checked)
{
setChildNodeCheckedState(e.Node, true);
if (e.Node.Parent != null) SetParentState(e.Node);
}
else
{
setChildNodeCheckedState(e.Node, false);
if (e.Node.Parent != null) SetParentState(e.Node);
}
}
}
/// <summary>
/// 选中节点时,若兄弟节点都选中则选中上级;取消选择时,取消上级选择
/// </summary>
/// <param name="currNode">当前节点</param>
private void SetParentState(TreeNode currNode)
{
TreeNode parentNode = currNode.Parent;
bool brotherChecked = true;
foreach (TreeNode node in parentNode.Nodes)
{
if (!node.Checked)
{
brotherChecked = false;
break;
}
}
parentNode.Checked = brotherChecked;
if (parentNode.Parent != null) SetParentState(parentNode);
}
/// <summary>
/// 选中节点之后,选中节点的所有子节点;取消选择时,取消所有子节点选择
/// </summary>
/// <param name="currNode">当前节点</param>
/// <param name="state">是否选中</param>
private void setChildNodeCheckedState(TreeNode currNode, bool state)
{
TreeNodeCollection nodes = currNode.Nodes;
if (nodes.Count > 0)
{
foreach (TreeNode tn in nodes)
{
tn.Checked = state;
setChildNodeCheckedState(tn, state);
}
}
}
public List<string> GetAllCheckedNodeNames()
{
var names = new List<string>();
foreach (TreeNode node in treeView1.Nodes)
{
if (node.Checked && !names.Contains(node.Name)) names.Add(node.Name);
GetCheckedChildrenName(node, names);
}
return names;
}
private void GetCheckedChildrenName(TreeNode currNode, List<string> names)
{
foreach (TreeNode node in currNode.Nodes)
{
if (node.Checked && !names.Contains(node.Name)) names.Add(node.Name);
GetCheckedChildrenName(node, names);
}
}
}
public class TreeViewEnhanced : TreeView
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x203) { m.Result = IntPtr.Zero; }//取消双击事件
else base.WndProc(ref m);
}
}
}