首先需要一个可绑定实体
[Serializable] public class TreeNodeModel { private Image _nodePic; ////// 设置图标 /// public Image NodelPic { get { return _nodePic; } set { _nodePic = value; } } /// /// 设置名称 /// public string NodeText { get; set; } private List _nodes = new List (); /// /// 子节点 /// public List Nodes { get { return _nodes; } set { _nodes = value; } } /// /// 数据源 /// public object DataSource { get; set; } private Color m_NodeBackgroundColor = Color.Empty; /// /// 背景颜色(默认白色) /// public Color NodeBackgroundColor { get { return m_NodeBackgroundColor; } set { m_NodeBackgroundColor = value; } } private bool m_canExpand = true; /// /// 是否可展开 /// public bool CanExpand { get { return m_canExpand; } set { m_canExpand = value; } } private int? _nodeHeight = null; /// /// 节点高度 /// public int? NodeHeight { get { return _nodeHeight; } set { _nodeHeight = value; } } private bool _isEventClick = true; /// /// 是否触发点击事件 /// public bool IsEventClick { get { return _isEventClick; } set { _isEventClick = value; } } private Color nodeForeColor=Color.Empty; /// /// 字体颜色 /// public Color NodeForeColor { get { return nodeForeColor; } set { nodeForeColor = value; } } }
然后是节点控件
设计文件
partial class UCTreeViewNode { ////// 必需的设计器变量。 /// private System.ComponentModel.IContainer components = null; /// /// 清理所有正在使用的资源。 /// /// 如果应释放托管资源,为 true;否则为 false。 protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// private void InitializeComponent() { this.lblName = new Km.Controls.Static.LabelEx(); this.lblUpDownPic = new Km.Controls.Static.LabelEx(); this.panNodePic = new Km.Controls.ExPanel.PanelEx(); this.panPic = new Km.Controls.ExPanel.PanelEx(); this.panPadding = new Km.Controls.ExPanel.PanelEx(); this.panNodePic.SuspendLayout(); this.SuspendLayout(); // // lblName // this.lblName.BackColor = System.Drawing.Color.Transparent; this.lblName.Dock = System.Windows.Forms.DockStyle.Fill; this.lblName.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.lblName.ForeColor = System.Drawing.Color.Silver; this.lblName.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; this.lblName.Location = new System.Drawing.Point(45, 0); this.lblName.Name = "lblName"; this.lblName.Size = new System.Drawing.Size(218, 65); this.lblName.TabIndex = 0; this.lblName.Text = "系统设置"; this.lblName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblUpDownPic // this.lblUpDownPic.Anchor = System.Windows.Forms.AnchorStyles.Right; this.lblUpDownPic.BackColor = System.Drawing.Color.Transparent; this.lblUpDownPic.Image = global::Km.Controls.Properties.Resources.下翻; this.lblUpDownPic.Location = new System.Drawing.Point(223, 21); this.lblUpDownPic.Name = "lblUpDownPic"; this.lblUpDownPic.Size = new System.Drawing.Size(37, 23); this.lblUpDownPic.TabIndex = 1; // // panNodePic // this.panNodePic.BackColor = System.Drawing.Color.Transparent; this.panNodePic.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.panNodePic.BottomborderStyleColor = System.Drawing.Color.Empty; this.panNodePic.BottomborderStyleSize = 0; this.panNodePic.BottomborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panNodePic.ContainerPanel = null; this.panNodePic.Controls.Add(this.panPic); this.panNodePic.Dock = System.Windows.Forms.DockStyle.Left; this.panNodePic.IsSelected = false; this.panNodePic.LeftborderStyleColor = System.Drawing.Color.Empty; this.panNodePic.LeftborderStyleSize = 0; this.panNodePic.LeftborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panNodePic.Location = new System.Drawing.Point(0, 0); this.panNodePic.Name = "panNodePic"; this.panNodePic.Radius = 0; this.panNodePic.Redraw = false; this.panNodePic.RightborderStyleColor = System.Drawing.Color.Empty; this.panNodePic.RightborderStyleSize = 0; this.panNodePic.RightborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panNodePic.Size = new System.Drawing.Size(45, 65); this.panNodePic.TabIndex = 2; this.panNodePic.TopborderStyleColor = System.Drawing.Color.Empty; this.panNodePic.TopborderStyleSize = 0; this.panNodePic.TopborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; // // panPic // this.panPic.BackgroundImage = global::Km.Controls.Properties.Resources.table_cell_bg1; this.panPic.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; this.panPic.BottomborderStyleColor = System.Drawing.Color.Empty; this.panPic.BottomborderStyleSize = 0; this.panPic.BottomborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPic.ContainerPanel = null; this.panPic.IsSelected = false; this.panPic.LeftborderStyleColor = System.Drawing.Color.Empty; this.panPic.LeftborderStyleSize = 0; this.panPic.LeftborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPic.Location = new System.Drawing.Point(10, 20); this.panPic.Name = "panPic"; this.panPic.Radius = 0; this.panPic.Redraw = false; this.panPic.RightborderStyleColor = System.Drawing.Color.Empty; this.panPic.RightborderStyleSize = 0; this.panPic.RightborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPic.Size = new System.Drawing.Size(25, 25); this.panPic.TabIndex = 0; this.panPic.TopborderStyleColor = System.Drawing.Color.Empty; this.panPic.TopborderStyleSize = 0; this.panPic.TopborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; // // panPadding // this.panPadding.BackColor = System.Drawing.Color.Transparent; this.panPadding.BottomborderStyleColor = System.Drawing.Color.Empty; this.panPadding.BottomborderStyleSize = 0; this.panPadding.BottomborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPadding.ContainerPanel = null; this.panPadding.Dock = System.Windows.Forms.DockStyle.Left; this.panPadding.IsSelected = false; this.panPadding.LeftborderStyleColor = System.Drawing.Color.Empty; this.panPadding.LeftborderStyleSize = 0; this.panPadding.LeftborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPadding.Location = new System.Drawing.Point(0, 0); this.panPadding.Name = "panPadding"; this.panPadding.Radius = 0; this.panPadding.Redraw = false; this.panPadding.RightborderStyleColor = System.Drawing.Color.Empty; this.panPadding.RightborderStyleSize = 0; this.panPadding.RightborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; this.panPadding.Size = new System.Drawing.Size(0, 65); this.panPadding.TabIndex = 3; this.panPadding.TopborderStyleColor = System.Drawing.Color.Empty; this.panPadding.TopborderStyleSize = 0; this.panPadding.TopborderStyleType = System.Windows.Forms.ButtonBorderStyle.None; // // UCTreeViewNode // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.Transparent; this.BottomborderStyleColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); this.BottomborderStyleSize = 1; this.BottomborderStyleType = System.Windows.Forms.ButtonBorderStyle.Solid; this.Controls.Add(this.lblUpDownPic); this.Controls.Add(this.lblName); this.Controls.Add(this.panNodePic); this.Controls.Add(this.panPadding); this.Name = "UCTreeViewNode"; this.RectColor = System.Drawing.Color.Red; this.Redraw = true; this.Size = new System.Drawing.Size(263, 65); this.panNodePic.ResumeLayout(false); this.ResumeLayout(false); } #endregion private Static.LabelEx lblName; private Static.LabelEx lblUpDownPic; private ExPanel.PanelEx panNodePic; private ExPanel.PanelEx panPic; private ExPanel.PanelEx panPadding; }
代码文件
public partial class UCTreeViewNode : UCBase { #region 属性 private int _nodeHeight = 65; ////// 节点高度 /// public int NodeHeight { get { return _nodeHeight; } set { _nodeHeight = value; } } private bool _isBrotherSingleExpanded = true; /// /// 兄弟节点是否仅有一个为展开状态 /// public bool IsBrotherSingleExpanded { get { return _isBrotherSingleExpanded; } set { _isBrotherSingleExpanded = value; } } private Image _downPic = Properties.Resources.下翻; /// /// 下翻图标 /// public Image DownPic { get { return _downPic; } set { _downPic = value; lblUpDownPic.Image = value; } } private Image _upPic = Properties.Resources.上翻; /// /// 上翻图标 /// public Image UpPic { get { return _upPic; } set { _upPic = value; } } private Color m_NodeBackgroundColor = Color.White; /// /// 背景颜色 /// public Color NodeBackgroundColor { get { return m_NodeBackgroundColor; } set { m_NodeBackgroundColor = value; this.BackColor = value; } } private bool m_isExpanded = false; /// /// 是否已展开 /// public bool IsExpanded { get { return m_isExpanded; } private set { m_isExpanded = value; } } private bool m_canExpand = false; /// /// 是否可展开 /// public bool CanExpand { get { return m_canExpand; } set { m_canExpand = value; lblUpDownPic.Visible = value; } } private TreeNodeModel m_source; /// /// 数据源 /// public TreeNodeModel Source { get { return m_source; } set { m_source = value; NodelPic = value.NodelPic; NodeText = value.NodeText; if (value.NodeBackgroundColor != Color.Empty) NodeBackgroundColor = value.NodeBackgroundColor; CanExpand = value.CanExpand; if (value.Nodes.Count > 0) { lblUpDownPic.Visible = true; } else { lblUpDownPic.Visible = false; } } } private string m_nodeText; /// /// 标题文字 /// public string NodeText { get { return m_nodeText; } set { m_nodeText = value; lblName.Text = value; } } private int m_nodeLeftPadding = 0; /// /// /// public int NodeLeftPadding { get { return m_nodeLeftPadding; } set { m_nodeLeftPadding = value; panPadding.Width = value; } } private Image _nodePic; /// /// 设置图标 /// public Image NodelPic { get { return _nodePic; } set { _nodePic = value; panPic.BackgroundImage = value; } } private List m_nodes = new List (); /// /// 子节点 /// public List Nodes { get { return m_nodes; } set { m_nodes = value; } } private UCTreeViewNode m_parentNode; /// /// 父节点 /// public UCTreeViewNode ParentNode { get { return m_parentNode; } set { m_parentNode = value; } } private Color _nodeForeColor = Color.Silver; /// /// 字体颜色 /// public Color NodeForeColor { get { return _nodeForeColor; } set { _nodeForeColor = value; lblName.ForeColor = value; } } private bool _isShowSplitLine = false; /// /// 是否显示分割线 /// public bool IsShowSplitLine { get { return _isShowSplitLine; } set { _isShowSplitLine = value; base.Redraw = value; } } private Color _splitLineColor= Color.FromArgb(54, 53, 58); /// /// 分割线颜色 /// public Color SplitLineColor { get { return _splitLineColor; } set { _splitLineColor = value; base.BottomborderStyleColor = value; } } /// /// 点击节点事件 /// public event EventHandler NodeMouseDown; #endregion public UCTreeViewNode() { InitializeComponent(); lblName.MouseDown += Node_MouseDown; lblUpDownPic.MouseDown += Node_MouseDown; } void Node_MouseDown(object sender, MouseEventArgs e) { if (NodeMouseDown != null && Source.IsEventClick) { NodeMouseDown(this, e); } Expanded(!IsExpanded); } /// /// 功能描述:展开节点 /// 作 者: /// 创建日期:2018-06-26 17:53:45 /// 任务编号: /// public void Expanded(bool blnExpanded = true) { if (CanExpand) { if (Nodes.Count > 0) { foreach (var item in Nodes) { // item.Visible = blnExpanded; if (blnExpanded) { item.Height = _nodeHeight; } else { item.Height = 0; item.ExpandedAll(false); } } IsExpanded = blnExpanded; if (blnExpanded) { lblUpDownPic.Image = UpPic; if (_isBrotherSingleExpanded) { //兄弟节点仅展开一个时,关闭其他节点 foreach (var item in ParentNode.Nodes) { if (item == this) continue; item.ExpandedAll(false); } } } else { lblUpDownPic.Image = DownPic; } } } } /// /// 功能描述:展开所有子节点 /// 作 者: /// 创建日期:2018-06-26 17:53:45 /// 任务编号: /// public void ExpandedAll(bool blnExpanded = true) { if (CanExpand && (!_isBrotherSingleExpanded || !blnExpanded)) { foreach (var item in Nodes) { //item.Visible = blnExpanded; if (blnExpanded) { item.Height = _nodeHeight; } else { item.Height = 0; } item.ExpandedAll(blnExpanded); } if (Nodes.Count > 0) { IsExpanded = blnExpanded; if (blnExpanded) { lblUpDownPic.Image = UpPic; } else { lblUpDownPic.Image = DownPic; } } } } }
另外需要重写Onpaint事件
protected override void OnPaint(PaintEventArgs e) { if (_redraw && !_isShowRect) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, _leftborderStyleColor,//7f9db9 _leftborderStyleSize, _leftborderStyleType, _topborderStyleColor,//7f9db9 _topborderStyleSize, _topborderStyleType, _rightborderStyleColor,//7f9db9 _rightborderStyleSize, _rightborderStyleType, _bottomborderStyleColor,//7f9db9 _bottomborderStyleSize, _bottomborderStyleType); } base.OnPaint(e); }
下面是树控件
设计文件
partial class UCTreeView { ////// 必需的设计器变量。 /// private System.ComponentModel.IContainer components = null; /// /// 清理所有正在使用的资源。 /// /// 如果应释放托管资源,为 true;否则为 false。 protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// private void InitializeComponent() { this.panSources = new System.Windows.Forms.FlowLayoutPanel(); this.SuspendLayout(); // // panSources // this.panSources.BackColor = System.Drawing.Color.Transparent; this.panSources.Dock = System.Windows.Forms.DockStyle.Fill; this.panSources.Location = new System.Drawing.Point(0, 0); this.panSources.Name = "panSources"; this.panSources.Size = new System.Drawing.Size(159, 485); this.panSources.TabIndex = 0; // // UCTreeView // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.BackColor = System.Drawing.Color.White; this.Controls.Add(this.panSources); this.Name = "UCTreeView"; this.Size = new System.Drawing.Size(159, 485); this.Resize += new System.EventHandler(this.UCTreeView_Resize); this.ResumeLayout(false); } #endregion private System.Windows.Forms.FlowLayoutPanel panSources; }
代码文件
public partial class UCTreeView : UserControl { #region 属性 private bool _isBrotherSingleExpanded = true; ////// 兄弟节点是否仅有一个为展开状态 /// [Description("兄弟节点是否仅有一个为展开状态"), Category("自定义属性")] public bool IsBrotherSingleExpanded { get { return _isBrotherSingleExpanded; } set { _isBrotherSingleExpanded = value; } } private List _dataSource; /// /// 数据源 /// public List DataSource { get { return _dataSource; } set { _dataSource = value; RefreshTree(); } } private Image _nodeDownPic = Properties.Resources.下翻; /// /// 下翻图标 /// [Description("下翻图标"), Category("自定义属性")] public Image NodeDownPic { get { return _nodeDownPic; } set { _nodeDownPic = value; } } private Image _nodeUpPic = Properties.Resources.上翻; /// /// 上翻图标 /// [Description("上翻图标"), Category("自定义属性")] public Image NodeUpPic { get { return _nodeUpPic; } set { _nodeUpPic = value; } } private Color _nodeBackgroundColor = Color.White; /// /// 节点背景颜色(如果数据源中设置了指定节点背景颜色,则优先使用数据源中的背景颜色) /// [Description("节点背景颜色(如果数据源中设置了指定节点背景颜色,则优先使用数据源中的背景颜色)"), Category("自定义属性")] public Color NodeBackgroundColor { get { return _nodeBackgroundColor; } set { _nodeBackgroundColor = value; } } private int _nodeHeight = 65; /// /// 节点高度(如果数据源中设置了指定节点高度,则优先使用数据源中的高度) /// [Description("节点高度(如果数据源中设置了指定节点高度,则优先使用数据源中的高度)"), Category("自定义属性")] public int NodeHeight { get { return _nodeHeight; } set { _nodeHeight = value; } } private int _nodeLeftPadding = 20; /// /// 子节点与父节点间偏移距离 /// [Description("子节点与父节点间偏移距离"), Category("自定义属性")] public int NodeLeftPadding { get { return _nodeLeftPadding; } set { _nodeLeftPadding = value; } } private Color _nodeForeColor = Color.Silver; /// /// 子节点字体颜色(如果数据源中设置了指定节点字体颜色,则优先使用数据源中的字体颜色) /// [Description("子节点字体颜色(如果数据源中设置了指定节点字体颜色,则优先使用数据源中的字体颜色)"), Category("自定义属性")] public Color NodeForeColor { get { return _nodeForeColor; } set { _nodeForeColor = value; } } private bool _nodeIsShowSplitLine = false; /// /// 是否显示分割线 /// [Description("节点是否显示分割线"), Category("自定义属性")] public bool NodeIsShowSplitLine { get { return _nodeIsShowSplitLine; } set { _nodeIsShowSplitLine = value; } } private Color _nodeSplitLineColor = Color.FromArgb(54, 53, 58); /// /// 分割线颜色 /// [Description("节点分割线颜色"), Category("自定义属性")] public Color NodeSplitLineColor { get { return _nodeSplitLineColor; } set { _nodeSplitLineColor = value; } } #endregion /// /// 节点点击事件 /// [Description("节点点击事件"), Category("自定义")] public event EventHandler NodeMouseDown; /// /// 功能描述:构造函数 /// 作 者: /// 创建日期:2018-06-26 16:58:51 /// 任务编号: /// public UCTreeView() { InitializeComponent(); } /// /// 功能描述:刷新列表 /// 作 者: /// 创建日期:2018-06-26 16:58:39 /// 任务编号: /// public void RefreshTree() { this.panSources.Controls.Clear(); if (_dataSource == null || _dataSource.Count <= 0) { return; } int intTabIndex = 0; UCTreeViewNode nodeBase = new UCTreeViewNode(); nodeBase.Tag = 0; LoadNode(nodeBase, _dataSource, ref intTabIndex, true); } /// /// 功能描述:加载节点 /// 作 者: /// 创建日期:2018-06-27 09:37:45 /// 任务编号: /// /// parentNode /// lstNodes /// intTabIndex /// blnVisible private void LoadNode( UCTreeViewNode parentNode, List lstNodes, ref int intTabIndex, bool blnVisible = false) { for (int i = 0; i < lstNodes.Count; i++) { var item = lstNodes[i]; UCTreeViewNode node = new UCTreeViewNode(); node.IsShowSplitLine = _nodeIsShowSplitLine; node.SplitLineColor = _nodeSplitLineColor; node.Tag = parentNode.Tag.ToIntExt() + 1; node.ParentNode = parentNode; node.UpPic = _nodeUpPic; node.DownPic = _nodeDownPic; node.Margin = new System.Windows.Forms.Padding(0); node.NodeLeftPadding = _nodeLeftPadding * parentNode.Tag.ToIntExt(); node.NodeMouseDown += node_NodeMouseDown; node.Anchor = AnchorStyles.Left | AnchorStyles.Right; node.Size = new System.Drawing.Size(this.Width, blnVisible ? (item.NodeHeight.HasValue ? item.NodeHeight.Value : _nodeHeight) : 0); node.NodeBackgroundColor = _nodeBackgroundColor; node.NodeForeColor = item.NodeForeColor == Color.Empty ? _nodeForeColor : item.NodeForeColor; node.TabIndex = ++intTabIndex; node.IsBrotherSingleExpanded = _isBrotherSingleExpanded; node.NodeHeight = (item.NodeHeight.HasValue ? item.NodeHeight.Value : _nodeHeight); parentNode.Nodes.Add(node); this.panSources.Controls.Add(node); Console.WriteLine(item.NodeText); if (item.Nodes != null && item.Nodes.Count > 0) { LoadNode(node, item.Nodes, ref intTabIndex, false); } node.Source = item; } } /// /// 功能描述:节点点击事件 /// 作 者: /// 创建日期:2018-06-27 09:31:44 /// 任务编号: /// /// sender /// e void node_NodeMouseDown(object sender, EventArgs e) { if (NodeMouseDown != null) { NodeMouseDown(sender, e); } } /// /// 改变大小时改变子项宽度,防止流控件横向显示多个 /// /// /// private void UCTreeView_Resize(object sender, EventArgs e) { this.SuspendLayout(); for (int i = this.panSources.Controls.Count-1; i >=0; i--) { this.panSources.Controls[i].Width = this.Width; } this.ResumeLayout(false); } }
代码中用到了其他一些自定义控件,替换为常规控件即可
调用如下
private void TestTreeView_Load(object sender, EventArgs e) { Listlst = new List (); for (int i = 0; i < 5; i++) { TreeNodeModel node = new TreeNodeModel() { CanExpand = true, DataSource = i, NodeBackgroundColor = Color.FromArgb(61, 60, 65), NodeText = string.Format("节点{0}", i), NodelPic = Properties.Resources.Exit }; for (int j = 0; j < 5; j++) { TreeNodeModel node2 = new TreeNodeModel() { CanExpand = true, DataSource = j, NodeForeColor = Color.Black, NodelPic = Properties.Resources.add, NodeText = string.Format("节点{0}-{1}", i, j) }; for (int k = 0; k < 5; k++) { TreeNodeModel node3 = new TreeNodeModel() { CanExpand = true, DataSource = k, NodeForeColor = Color.Black, NodeText = string.Format("节点{0}-{1}-{2}", i, j, k) }; node2.Nodes.Add(node3); } node.Nodes.Add(node2); } lst.Add(node); } this.ucTreeView1.DataSource = lst; } private void ucTreeView1_NodeMouseDown(object sender, EventArgs e) { UCTreeViewNode node = sender as UCTreeViewNode; TreeNodeModel model = node.Source; }
支持设置每个节点颜色,字体颜色,图标,展开关闭图标,是否显示分割线及颜色
效果如下