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;
        }

    }
}
posted @ 2011-06-04 14:14  liulun  阅读(1715)  评论(8编辑  收藏  举报