using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Design; using System.Linq; using System.Windows.Forms; namespace DPumpHydr.WinFrmUI.WenSkin.Controls { [ToolboxBitmap(typeof(TreeView))] public partial class WenTreeView : TreeView { public WenTreeView() { InitializeComponent(); this.DrawMode = TreeViewDrawMode.OwnerDrawText; this.ItemHeight = 30; this.BackColor = Color.FromArgb(45, 45, 48); this.FullRowSelect = true; } #region 委托事件 public delegate void TreeNodeDrawEventHandler(object sender, DragTreeNodeEventArgs e); public delegate void WenTreeViewEventHandler(object sender, WenTreeViewEventArgs e); [Category("Wen")] [Description("拖拽节点发生事件")] public event TreeNodeDrawEventHandler TreeNodeDrag; [Category("Wen")] [Description("节点被点击事件")] public event WenTreeViewEventHandler TreeNodeItemClick; [Category("Wen")] [Description("节点勾选事件")] public event WenTreeViewEventHandler TreeNodeCheck; #endregion #region 私有属性 private List checkBoxSelected; private DataListColumnCollection columns; private TreeDataSourceNode treeDataSourceNode; private object dataSource { get; set; } private StringFormat StringConters { get; set; } = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap) { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; #endregion #region 公有属性 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Category("Wen")] [Description("列数据")] [Editor(typeof(Design.Editor.WenCollectionEditor),typeof(UITypeEditor))] public DataListColumnCollection Columns => columns ??= new DataListColumnCollection(this); [Category("Wen")] [Description("绑定数据Text默认值")] [DefaultValue(null)] public string DefaultTextColumn { get; set; } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Category("Wen")] [Description("绑定数据节点信息设置")] [DefaultValue(false)] public TreeDataSourceNode TreeDataSourceNode => treeDataSourceNode ??= new TreeDataSourceNode(); [Category("Wen")] [Description("获取勾选项")] [Browsable(false)] public List CheckBoxSelected => checkBoxSelected ??= new List(); [Browsable(false), DefaultValue(null)] public object DataSource { get => dataSource; set { dataSource = value; DataBind(); } } #endregion #region 绑定数据 private void DataBind() { if (dataSource == null) return; this.Nodes.Clear(); //判定是否是数据绑定输结构模式 if (TreeDataSourceNode.TreeDataSource) { bindDataRows.Clear(); if (dataSource is DataTable dt) DataBindTreeNode(dt, this.Nodes, TreeDataSourceNode.RootContent); } //若不是直接绑定数据 else { switch (dataSource) { case DataTable dt: DataBind(dt); break; case DataSet ds: DataBind(ds.Tables[0]); break; case IList lists: foreach (var item in lists) { var infos = item.GetType().GetProperties().ToList(); WenTreeNode node = new WenTreeNode(this) { Tag = item, Text = DefaultTextColumn == null ? item.GetType().GetProperties()[0]?.GetValue(item, null)?.ToString() : infos.Find(a => a.Name.ToUpper() == DefaultTextColumn.ToUpper())?.GetValue(item, null)?.ToString(), }; foreach (DataListColumn column in Columns) { node.Cells.Add(new WenTreeViewCell(column.CloumnName, infos.Find(a => a.Name.ToUpper() == column.CloumnName.ToUpper())?.GetValue(item, null)?.ToString())); } this.Nodes.Add(node); } break; default: break; } } void DataBind(DataTable dt) { foreach (DataRow dr in dt.Rows) { WenTreeNode node = new WenTreeNode(this) { Tag = dr, Text = DefaultTextColumn == null ? dr[0]?.ToString() : dt.Columns.Contains(DefaultTextColumn) ? dr[DefaultTextColumn]?.ToString() : null, }; foreach (DataListColumn column in Columns) { node.Cells.Add(new WenTreeViewCell(column.CloumnName, dt.Columns.Contains(column.CloumnName) ? dr[column.CloumnName] : null)); } this.Nodes.Add(node); } } //折叠全部数据 this.CollapseAll(); } List bindDataRows = new List(); private void DataBindTreeNode(DataTable dt, TreeNodeCollection nodes, string value) { DataRow[] rows = dt.Select($"{TreeDataSourceNode.ParentNode}=\'{value}\'"); foreach (DataRow dr in rows) { if (bindDataRows.Contains(dr)) continue; WenTreeNode node = new WenTreeNode(this) { Tag = dr, Text = DefaultTextColumn == null ? dr[0]?.ToString() : dt.Columns.Contains(DefaultTextColumn) ? dr[DefaultTextColumn]?.ToString() : null, }; foreach (DataListColumn column in Columns) { if (dt.Columns.Contains(column.CloumnName)) { WenTreeViewCell cell = new WenTreeViewCell(column.CloumnName, dr[column.CloumnName]); cell.ValueChange += (s, e) => { dr[column.CloumnName] = e.Message; }; node.Cells.Add(cell); } } nodes.Add(node); string parentValue = dr[TreeDataSourceNode.ChildNode]?.ToString(); DataBindTreeNode(dt, node.Nodes, parentValue); bindDataRows.Add(dr); } } #endregion #region 重绘事件 protected override void OnPaint(PaintEventArgs e) { } protected override void OnDrawNode(DrawTreeNodeEventArgs e) { //base.OnDrawNode(e); Graphics g = e.Graphics; g.SetGDIHigh(); Rectangle rec = new Rectangle(e.Bounds.X, e.Bounds.Y - 1, Width - e.Bounds.X, e.Bounds.Height + 1); //正在需要绘制的项目 TreeNode node = e.Node; //此项还不清楚是 if (rec.X < 1) return; //获取当前选中项目 TreeNode selectNode = this.SelectedNode; if (selectNode == node) g.FillRectangle(new SolidBrush(Color.FromArgb(63, 63, 70)), rec); else //整行设置重绘背景颜色 g.FillRectangle(new SolidBrush(this.BackColor), rec); //绘制一条长线 g.DrawLine(Pens.Gray, rec.X, rec.Y + rec.Height - 1, rec.X + rec.Width, rec.Y + rec.Height - 1); //设置文字颜色,和单元格样式 var brus = Brushes.White; if (selectNode == node) brus = Brushes.White; //当行数据为空或者其他数据值为空的时候显示文本 if(node is WenTreeNode wennode) { if (Columns.Count == 0) { g.DrawString(node.Text, Font, brus, rec, StringConters); return; } int rowsumwidth = rec.X; foreach (DataListColumn c in Columns) { var recleft = rowsumwidth; int index = Columns.IndexOf(c); //绘制宽度 int width = c.Width; if (index == 0) width = c.Width - node.Level * Indent; rowsumwidth += width; Rectangle rectangle = new Rectangle(recleft, rec.Y, width, ItemHeight - 1); string text = wennode.Cells[c.CloumnName]?.Value?.ToString(); g.DrawString(text, Font, brus, rectangle, StringConters); } } else { g.DrawString(node.Text, Font, brus, rec, StringConters); } } #endregion #region 鼠标点击事件 protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); TreeNode node = this.GetNodeAt(e.X, e.Y); this.SelectedNode = node; TreeNodeItemClick?.Invoke(this, new WenTreeViewEventArgs(node) { TreeNodes = CheckBoxSelected }); } protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); this.SelectedNode = this.GetNodeAt(e.X, e.Y); Rectangle rec = this.SelectedNode.Bounds; if (rec.Contains(e.Location)) return; if (this.SelectedNode.IsExpanded) this.SelectedNode.Collapse(); else this.SelectedNode.Expand(); } #endregion #region 拖动移动节点 protected override void OnItemDrag(ItemDragEventArgs e) { base.OnItemDrag(e); if (e.Button == MouseButtons.Left) { if(e.Item is TreeNode node) this.DoDragDrop(node, DragDropEffects.Move); } } protected override void OnDragEnter(DragEventArgs e) { base.OnDragEnter(e); if (e.Data.GetDataPresent(typeof(TreeNode))|| e.Data.GetDataPresent(typeof(WenTreeNode))) { e.Effect = DragDropEffects.Move; } else { e.Effect = DragDropEffects.None; } } protected override void OnDragDrop(DragEventArgs e) { base.OnDragDrop(e); var moveNode = (e.Data.GetData(typeof(WenTreeNode)) as WenTreeNode) ?? (e.Data.GetData(typeof(TreeNode)) as TreeNode); //根据鼠标坐标确定要移动到的目标节点 Point pt; TreeNode targeNode; pt = this.PointToClient(new Point(e.X, e.Y)); targeNode = this.GetNodeAt(pt); //判定节点情况是否可移动 if (moveNode == null || targeNode == null || targeNode == moveNode || BoolMoneNode(moveNode, targeNode) || targeNode == moveNode.Parent) return; if (!OnTreeNodeDraw(moveNode, targeNode)) return; moveNode.Remove(); targeNode.Nodes.Add(moveNode); //更新当前拖动的节点选择 this.SelectedNode = moveNode; //展开目标节点,便于显示拖放效果 targeNode.Expand(); } //判定移动的节点是否是节点的子节点 private bool BoolMoneNode(TreeNode node, TreeNode targeNode) { return nodes(node).Exists(a => a == targeNode); List nodes(TreeNode nes) { List ns = new List(); if(nes?.Nodes.Count>0) foreach (TreeNode no in nes.Nodes) { if (no.Nodes.Count > 0) ns.AddRange(nodes(no)); ns.Add(no); } return ns; } } public bool OnTreeNodeDraw(TreeNode node, TreeNode targeNode) { var e = new DragTreeNodeEventArgs(node, targeNode); TreeNodeDrag?.Invoke(this, e); return e.State; } #endregion //若tag 绑定值得情况,将datarowview的值更新 protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e) { base.OnAfterLabelEdit(e); if (e.Label == null) return; if (e.Node is WenTreeNode node) { node.Cells[DefaultTextColumn].Value = e.Label; } } #region 勾选引发事件 protected override void OnAfterCheck(TreeViewEventArgs e) { base.OnAfterCheck(e); if (e.Node.Checked) { if (!CheckBoxSelected.Contains(e.Node)) { CheckBoxSelected.Add(e.Node); } } else { if (CheckBoxSelected.Contains(e.Node)) { CheckBoxSelected.Remove(e.Node); } } WenTreeViewEventArgs wenTreeViewEventArgs = new WenTreeViewEventArgs(e.Node, e.Action) { TreeNodes = CheckBoxSelected }; TreeNodeCheck?.Invoke(this, wenTreeViewEventArgs); } #endregion [TypeConverter(typeof(ExpandableObjectConverter))] public class DataListColumn { public DataListColumn() { } [DefaultValue("Name")] public string Name { get; set; } = "Name"; [DefaultValue("CloumnName")] public string CloumnName { get; set; } = "CloumnName"; [DefaultValue("标题")] public string Text { get; set; } = "标题"; [DefaultValue(120)] public int Width { get; set; } = 120; public override string ToString() { if (Name != Text) return $"{Name}[{Text}]"; else return Name; } } public class DataListColumnCollection : WenCollection { private readonly WenTreeView owner; public DataListColumnCollection(WenTreeView owner) { this.owner = owner; } public DataListColumn this[int index] => Items.Count <= index ? null : Items[index] as DataListColumn; } public class WenTreeViewCell { private object value; public event WenSkin.EventClass.MessageEventHandler ValueChange; public WenTreeViewCell() { } public WenTreeViewCell(string name, object value) { Name = name; Value = value; } public string Name { get; set; } public object Value { get => value; set { this.value = value; ValueChange?.Invoke(this, new EventClass.MessageEventArgs(value?.ToString())); } } } public class WenTreeViewCellCollection : WenCollection { public WenTreeViewCell this[int index] { get => Items.Count <= index ? null : (WenTreeViewCell)Items[index]; set { if (Items.Count <= index) return; Items[index] = value; } } public WenTreeViewCell this[string key] { get { foreach (var item in Items) { if (item is WenTreeViewCell cell) { if (cell.Name.ToUpper() == key.ToUpper()) { return cell; } } } return null; } } } public class WenTreeNode : TreeNode { private readonly WenTreeView owner; public WenTreeNode():base() { } public WenTreeNode(WenTreeView owner):base() { this.owner = owner; } private WenTreeViewCellCollection cells; public WenTreeViewCellCollection Cells => cells ??= new WenTreeViewCellCollection(); } public class WenTreeViewEventArgs : TreeViewEventArgs { public WenTreeViewEventArgs(TreeNode node) : base(node) { } public WenTreeViewEventArgs(TreeNode node, TreeViewAction action) : base(node, action) { } public List TreeNodes { get; set; } } public class DragTreeNodeEventArgs : TreeViewEventArgs { public DragTreeNodeEventArgs(TreeNode node,TreeNode targe) : base(node) { this.TargeTreeNode = targe; } public TreeNode TargeTreeNode { get;private set; } public bool State { get; set; } = true; } } }