之前寫過NetronLight開源框架
C#使用開源框架NetronLight繪制流程圖-CSDN博客
我們這里將TreeView樹圖的節點內容展示到NetronLight圖表中,按照樹的層次【深度Level】展示
新建窗體應用程序ShowTreeNodeToDiagram,將默認的Form1重命名為FormShowNode,
右鍵解決方案ShowTreeNodeToDiagram,添加→現有項目,將NetronLight添加到項目中。
右鍵項目ShowTreeNodeToDiagram,添加引用,引用項目NetronLight
修改NetronLight.GraphControl 控件增加【連線集合】屬性:
/// <summary>/// Gets or sets the collection of connections on the canvas/// </summary>public ConnectionCollection Connections{get { return connections; }set { connections = value; }}
?窗體FormShowNode 設計器如下圖:
窗體設計器程序如下:
FormShowNode.Designer.cs?文件
namespace ShowTreeNodeToDiagram
{partial class FormShowNode{/// <summary>/// 必需的設計器變量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的資源。/// </summary>/// <param name="disposing">如果應釋放托管資源,為 true;否則為 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗體設計器生成的代碼/// <summary>/// 設計器支持所需的方法 - 不要修改/// 使用代碼編輯器修改此方法的內容。/// </summary>private void InitializeComponent(){this.tvGeography = new System.Windows.Forms.TreeView();this.graphControl1 = new NetronLight.GraphControl();this.btnShowDiagram = new System.Windows.Forms.Button();this.SuspendLayout();// // tvGeography// this.tvGeography.Location = new System.Drawing.Point(5, 44);this.tvGeography.Name = "tvGeography";this.tvGeography.Size = new System.Drawing.Size(280, 563);this.tvGeography.TabIndex = 0;// // graphControl1// this.graphControl1.Location = new System.Drawing.Point(297, 7);this.graphControl1.Name = "graphControl1";this.graphControl1.ShowGrid = true;this.graphControl1.Size = new System.Drawing.Size(1200, 600);this.graphControl1.TabIndex = 1;this.graphControl1.Text = "graphControl1";// // btnShowDiagram// this.btnShowDiagram.Font = new System.Drawing.Font("宋體", 12F);this.btnShowDiagram.Location = new System.Drawing.Point(40, 9);this.btnShowDiagram.Name = "btnShowDiagram";this.btnShowDiagram.Size = new System.Drawing.Size(158, 26);this.btnShowDiagram.TabIndex = 2;this.btnShowDiagram.Text = "展示樹節點到圖表";this.btnShowDiagram.UseVisualStyleBackColor = true;this.btnShowDiagram.Click += new System.EventHandler(this.btnShowDiagram_Click);// // FormShowNode// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1523, 611);this.Controls.Add(this.btnShowDiagram);this.Controls.Add(this.graphControl1);this.Controls.Add(this.tvGeography);this.Name = "FormShowNode";this.Text = "將樹圖節點展示到NetronLight圖表中-斯內科";this.Load += new System.EventHandler(this.FormShowNode_Load);this.ResumeLayout(false);}#endregionprivate System.Windows.Forms.TreeView tvGeography;private NetronLight.GraphControl graphControl1;private System.Windows.Forms.Button btnShowDiagram;}
}
測試程序如下:
FormShowNode.cs文件
using NetronLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace ShowTreeNodeToDiagram
{public partial class FormShowNode : Form{public FormShowNode(){InitializeComponent();}private void GenerateGeographyMap() {TreeNode rootNode = new TreeNode("中國");TreeNode node1 = new TreeNode("廣東省");TreeNode node2 = new TreeNode("河南省");TreeNode node3 = new TreeNode("江蘇省");TreeNode node4 = new TreeNode("廣州市");TreeNode node5 = new TreeNode("深圳市");TreeNode node6 = new TreeNode("惠州市");TreeNode node7 = new TreeNode("鄭州市");TreeNode node8 = new TreeNode("許昌市");TreeNode node9 = new TreeNode("南陽市");TreeNode node10 = new TreeNode("南京市");TreeNode node11 = new TreeNode("常州市");TreeNode node12 = new TreeNode("越秀區");TreeNode node13 = new TreeNode("荔灣區");TreeNode node14 = new TreeNode("福田區");TreeNode node15 = new TreeNode("南山區");TreeNode node16 = new TreeNode("寶安區");TreeNode node17 = new TreeNode("博羅縣");TreeNode node18 = new TreeNode("中原區");TreeNode node19 = new TreeNode("魏都區");TreeNode node20 = new TreeNode("臥龍區");TreeNode node21 = new TreeNode("江寧區");TreeNode node22 = new TreeNode("金壇區");TreeNode node23 = new TreeNode("洛陽市");node4.Nodes.AddRange(new TreeNode[] { node12, node13 });node5.Nodes.AddRange(new TreeNode[] { node14, node15, node16 });node6.Nodes.AddRange(new TreeNode[] { node17 });node7.Nodes.AddRange(new TreeNode[] { node18 });node8.Nodes.AddRange(new TreeNode[] { node19 });node9.Nodes.AddRange(new TreeNode[] { node20 });node10.Nodes.AddRange(new TreeNode[] { node21 });node11.Nodes.AddRange(new TreeNode[] { node22 });node1.Nodes.AddRange(new TreeNode[] { node4, node5, node6 });node2.Nodes.AddRange(new TreeNode[] { node7, node8, node9, node23 });node3.Nodes.AddRange(new TreeNode[] { node10, node11 });rootNode.Nodes.AddRange(new TreeNode[] { node1, node2, node3 });tvGeography.Nodes.Clear();tvGeography.Nodes.Add(rootNode);}private void FormShowNode_Load(object sender, EventArgs e){GenerateGeographyMap();tvGeography.ExpandAll();}/// <summary>/// 查找指定深度的所有節點集合/// 獲取指定深度的節點集合,這些節點的屬于同一行號【Y坐標一致】/// </summary>/// <param name="rootNode"></param>/// <param name="level"></param>/// <returns></returns>private List<TreeNode> GetCurrentLevelNodes(TreeNode rootNode, int level){List<TreeNode> nodeList = new List<TreeNode>();if (rootNode.Level == level){nodeList.Add(rootNode);}for (int i = 0; i < rootNode.Nodes.Count; i++){TreeNode current = rootNode.Nodes[i];//如果當前節點的深度 不等于 已知深度,就繼續遞歸。當前節點的深度 等于 已知深度,就添加該節點if (current.Level == level){nodeList.Add(current);}else{List<TreeNode> tempList = GetCurrentLevelNodes(current, level);if (tempList.Count > 0){nodeList.AddRange(tempList);}}}return nodeList;}/// <summary>/// 獲取樹節點的最大深度Level/// </summary>/// <param name="rootNode"></param>/// <returns></returns>private int GetMaxLevel(TreeNode rootNode){int level = rootNode.Level;//默認當前節點的深度for (int i = 0; i < rootNode.Nodes.Count; i++){TreeNode current = rootNode.Nodes[i];//如果當前節點的深度 比 上一次的深度大,就繼續遞歸if (current.Level > level){return GetMaxLevel(current);}}return level;}/// <summary>/// 通過樹節點來獲取對應的形狀節點/// </summary>/// <param name="treeNode"></param>/// <returns></returns>private ShapeBase GetShapeByTreeNode(TreeNode treeNode){SimpleRectangle shapeNode = graphControl1.Shapes.Cast<SimpleRectangle>().ToList().Find(x => x.Text == treeNode.Text);return shapeNode;}/// <summary>/// 父子節點進行連線:連線端點Bottom, Left, Right, Top。由起始節點的底部端點 連接到 終止節點的頂部端點/// </summary>/// <param name="fromNode"></param>/// <param name="toNode"></param>private void AddLink(TreeNode fromNode, TreeNode toNode) {ShapeBase fromShape = GetShapeByTreeNode(fromNode);ShapeBase toShape = GetShapeByTreeNode(toNode);if (fromShape != null && toShape != null){//連線端點Bottom, Left, Right, Top。由起始節點的底部端點 連接到 終止節點的頂部端點graphControl1.AddConnection(fromShape.Connectors[0], toShape.Connectors[3]);}}/// <summary>/// 生成一個形狀節點/// </summary>/// <param name="treeNode"></param>/// <param name="point"></param>private void GenerateShapeNode(TreeNode treeNode, Point point) {SimpleRectangle diagramNode = new SimpleRectangle(graphControl1);diagramNode.Text = treeNode.Text;//主程序提示 特殊處理diagramNode.Width = 80;diagramNode.Height = 30;diagramNode.Location = point;diagramNode.ShapeColor = Color.GreenYellow;graphControl1.Shapes.Add(diagramNode);}/// <summary>/// 生成節點之間的連線/// </summary>private void GenerateLinks(TreeNode treeNode){Stack<TreeNode> nodes = new Stack<TreeNode>();nodes.Push(treeNode);while (nodes.Count > 0){TreeNode fromNode = nodes.Pop();for (int i = 0; i < fromNode.Nodes.Count; i++){TreeNode toNode = fromNode.Nodes[i];AddLink(fromNode, toNode);nodes.Push(toNode);//將當前子節點插入集合中,繼續連線}}}private void btnShowDiagram_Click(object sender, EventArgs e){graphControl1.Connections.Clear();//清除所有連線graphControl1.Shapes.Clear();////清除所有形狀節點//根節點是第一個TreeNode rootNode = tvGeography.Nodes[0];int maxLevel = GetMaxLevel(rootNode);//獲取樹節點的最大深度//按照節點的深度Level將樹節點進行分組for (int level = 0; level <= maxLevel; level++){List<TreeNode> nodeList = GetCurrentLevelNodes(rootNode, level);int offsetX = (graphControl1.Width - 80) / (nodeList.Count + 1);for (int i = 0; i < nodeList.Count; i++){GenerateShapeNode(nodeList[i], new Point(3 + offsetX * (i + 1), 20 + 140 * level));}}//生成節點之間的連線GenerateLinks(rootNode);//獲取指定深度的節點集合。這些節點的屬于同一行號【Y坐標一致】graphControl1.Invalidate();}}
}
運行如圖:
點擊展示按鈕
?