silverlight绘制树形结构拓扑图
先上个图片:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using EMS.Host.DBModels; using EMS.Host.WCFService; namespace EMS.UI.Controls { public partial class BoxTree : UserControl { /// <summary> /// 所有节点的集合 /// </summary> public List<Node> Nodes = new List<Node>(); public Node FirstNode; /// <summary> /// this宽度 /// </summary> public double totalWidth; /// <summary> /// this高度 /// </summary> public double totalHight; /// <summary> /// 元素宽度 /// </summary> public double buttonWidth; /// <summary> /// 元素高度 /// </summary> public double buttonHeight; public double plusButtonWidth; public double plusButtonHeight; public double levelHight; public double minHorizontalSpace; public double minVerticalSpace; public double fontSize; public SolidColorBrush LinesStroke; public double LinesStrokeThickness; public double drawingScale = 1; public RoutedEventHandler AddEvent; public RoutedEventHandler DelEvent; public RoutedEventHandler EditEvent; int ammeterType; public int AmmeterType { get { return ammeterType; } set { ammeterType = value; } } private EMSDS _dbContext; public EMSDS DBContext { get { return _dbContext; } set { _dbContext = value; } } public BoxTree() { InitializeComponent(); } private void init() { } public void Refresh() { MyCanvas.Children.Clear(); buttonWidth = 200 * drawingScale; buttonHeight = 50 * drawingScale; minHorizontalSpace = 10 * drawingScale; minVerticalSpace = 20 * drawingScale; plusButtonWidth = 12 * drawingScale; plusButtonHeight = 12 * drawingScale; fontSize = 10 * drawingScale; LinesStrokeThickness = 1 * drawingScale; levelHight = buttonHeight + minVerticalSpace * 2; MyCanvas.Width = buttonWidth; MyCanvas.Height = buttonHeight; totalWidth = MyCanvas.Width; totalHight = MyCanvas.Height; Nodes[0].ChildWidth = buttonWidth + minHorizontalSpace; Nodes[0].StartX = 0; Nodes[0].X = Nodes[0].ChildWidth / 2; SetLevel(FirstNode, 1); CalculateWidth(FirstNode); CalculateX(FirstNode); DrawSonNodes(FirstNode); MyCanvas.Width += 300; } private void SetLevel(Node parent, int level) { parent.Level = level; if (totalHight < levelHight * (level + 2)) { totalHight = levelHight * (level + 2); MyCanvas.Height = totalHight; } var result = from n in Nodes where n.PID == parent.ID select n; Node[] nodes = result.ToArray(); parent.SubNodes = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i].NodeOrder = i + 1; nodes[i].ChildWidth = buttonWidth + minHorizontalSpace; SetLevel(nodes[i], parent.Level + 1); } } private void CalculateWidth(Node parent) { if (parent.SubNodes > 0) { var result = from n in Nodes where n.PID == parent.ID orderby n.NodeOrder select n; Node[] nodes = result.ToArray(); double width = 0; for (int i = 0; i < nodes.Length; i++) { CalculateWidth(nodes[i]); width = width + nodes[i].ChildWidth; } if (width > parent.ChildWidth) { parent.ChildWidth = width; if (MyCanvas.Width < width) { MyCanvas.Width = width; } } } } private void CalculateX(Node parent) { if (parent.SubNodes > 0) { var result = from n in Nodes where n.PID == parent.ID orderby n.NodeOrder select n; Node[] nodes = result.ToArray(); double start = parent.StartX; for (int i = 0; i < nodes.Length; i++) { nodes[i].StartX = start; nodes[i].X = nodes[i].StartX + nodes[i].ChildWidth / 2; CalculateX(nodes[i]); start = start + nodes[i].ChildWidth; } if (nodes.Length > 1) { parent.X = (nodes[0].X + nodes[nodes.Length - 1].X) / 2; } else { parent.X = nodes[0].X; } } } private void DrawSonNodes(Node parent) { if (parent.PID == null) { CreateNode(parent); } var results = (from n in Nodes where n.PID == parent.ID orderby n.NodeOrder select n).ToArray(); if (results.Count() > 0) { var topLine = new Line(); topLine.X1 = results[0].X + buttonWidth / 2; topLine.X2 = results[results.Length - 1].X + buttonWidth / 2; topLine.Y1 = parent.Level * levelHight + buttonHeight + minVerticalSpace; topLine.Y2 = parent.Level * levelHight + buttonHeight + minVerticalSpace; topLine.StrokeThickness = 1; topLine.Stroke = new SolidColorBrush(Colors.Black); MyCanvas.Children.Add(topLine); } foreach (Node p in results) { CreateNode(p); DrawSonNodes(p); } } private void CreateNode(Node node) { var c = new Canvas(); c.Width = buttonWidth; c.Height = buttonHeight; var b = new Border(); b.BorderBrush = new SolidColorBrush(Colors.Black); b.BorderThickness = new Thickness(1); b.Width = c.Width; b.Height = c.Height; c.Children.Add(b); var s = new StackPanel(); s.VerticalAlignment = System.Windows.VerticalAlignment.Center; s.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; b.Child = s; var tb = new TextBlock() { TextWrapping = TextWrapping.Wrap, TextAlignment = System.Windows.TextAlignment.Center, VerticalAlignment = System.Windows.VerticalAlignment.Center }; tb.Text = node.Title; var delbtn = new Button(); delbtn.Content = "删"; var addbtn1 = new Button(); addbtn1.Content = "子"; var addbtn2 = new Button(); addbtn2.Content = "改"; delbtn.Margin = new Thickness(4); addbtn1.Margin = new Thickness(4); addbtn2.Margin = new Thickness(4); delbtn.Width = c.Width / 3 - 10; addbtn1.Width = c.Width / 3 - 10; addbtn2.Width = c.Width / 3 - 10; addbtn1.Tag = node.ID; addbtn2.Tag = node.ID; delbtn.Tag = node.ID; addbtn1.Click += AddEvent; delbtn.Click += DelEvent; addbtn2.Click += EditEvent; var sp = new StackPanel(); sp.Orientation = Orientation.Horizontal; sp.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; sp.Children.Add(addbtn2); sp.Children.Add(addbtn1); sp.Children.Add(delbtn); s.Children.Add(tb); s.Children.Add(sp); Canvas.SetLeft(c, node.X); Canvas.SetTop(c, node.Level * levelHight); this.MyCanvas.Children.Add(c); if (node.PID != null) { var topLine = new Line(); topLine.X1 = node.X + buttonWidth / 2; topLine.X2 = node.X + buttonWidth / 2; topLine.Y1 = node.Level * levelHight - minVerticalSpace; topLine.Y2 = node.Level * levelHight; topLine.StrokeThickness = 1; topLine.Stroke = new SolidColorBrush(Colors.Black); MyCanvas.Children.Add(topLine); } if ((from n in Nodes where n.PID == node.ID select n).Count() > 0) { var topLine = new Line(); topLine.X1 = node.X + buttonWidth / 2; topLine.X2 = node.X + buttonWidth / 2; topLine.Y1 = node.Level * levelHight + buttonHeight; topLine.Y2 = node.Level * levelHight + buttonHeight + minVerticalSpace; topLine.StrokeThickness = 1; topLine.Stroke = new SolidColorBrush(Colors.Black); MyCanvas.Children.Add(topLine); } } public class Node { public Guid ID; public Guid? PID; public string Title; public int Level = 1; public int SubNodes = 0; public int NodeOrder = 1; public double ChildWidth; public double X; public double StartX; } } }