技术开发 频道

Silverlight实现递归构造关系图实例

  4,我们需要算出节点对象的左边距,在第3步中我没能找到方法,于是想到利用每一级的元素个数来计算每个节点的位置,然后使用每一级的平均节点距离*节点的索引便可得到left

//构造各层及数量
            foreach (TaskPro t in listOfTaskPro)
            {
                bool IsExist
= false;
                foreach (TaskCount tc in listTopAndTasks)
                {
                    IsExist
= tc.Top==t.top?true:false;
                }
                
if (!IsExist)
                {
                    listTopAndTasks.Add(
new TaskCount() { Top = t.top, Tasks = new List<Task>() });
                }
                var topAndTasks
= listTopAndTasks.Where(m => m.Top == t.top).FirstOrDefault();
                topAndTasks.Tasks.Add(t.task);
            }
            
//构造index
            foreach (TaskPro t in listOfTaskPro)
            {
                
for (int i = 0; i < listTopAndTasks.Count; i++)
                {
                    
for (int j = 0; j < listTopAndTasks[i].Tasks.Count; j++)
                    {
                        
if (listTopAndTasks[i].Tasks[j].ID == t.task.ID)
                        {
                            t.index
= j + 1;
                        }
                    }
                }
            }
            
//构造left
            
for (int i = 0; i < listOfTaskPro.Count; i++)
            {
                
if (listOfTaskPro[i].task.ParentID == 0)
                {
                    listOfTaskPro[i].left
= this.canvas1.Width / 2;
                }
                
else
                {
                    var childCount
= listOfTaskPro.Where(m => m.task.ParentID == listOfTaskPro[i].task.ParentID).Count();
                    var parentLeft
= listOfTaskPro.Where(m => m.task.ID == listOfTaskPro[i].task.ParentID).FirstOrDefault().left;
                    var perLength
= parentLeft * 1.5 / (childCount + 1);
                    listOfTaskPro[i].left
= listOfTaskPro[i].index * perLength;
                }
            }


 

  5,至此,节点对象已经具备了left,top属性,我们只需要找到每个节点的父节点即可将两个几点的坐标确定,进而进行划线的操作了。

foreach (TaskPro t in listOfTaskPro)
            {
                AddBtn(t.task.Name, t.left, t.top);
                
if (t.task.ParentID != 0)
                {
                    TaskPro tp
= listOfTaskPro.Where(m => m.task.ID == t.task.ParentID).FirstOrDefault();
                    AddLine(tp.left
+ buttonWidth / 2, tp.top + buttonHeight, t.left + buttonWidth / 2, t.top);
                }
            }

 

  6,添加按钮及划线的方法

#region 添加按钮及线条
        
double buttonHeight = 20;
        
double buttonWidth = 50;

        void AddBtn(
string content, double left, double top)
        {
            Button btn
= new Button();
            btn.Content
= content;
            btn.Width
= buttonWidth;
            btn.Height
= buttonHeight;
            this.canvas1.Children.Add(btn);
            Canvas.SetLeft(btn,
left);
            Canvas.SetTop(btn, top);
        }

//画线方法,只需要有起始亮点的坐标即可

        void AddLine(
double startLeft, double startTop, double endLeft, double endTop)
        {
            Path p
= new Path();
            LineGeometry geometry
= new LineGeometry();
            SolidColorBrush brush
= new SolidColorBrush();
            brush.Color
= Colors.Black;
            geometry.StartPoint
= new Point(startLeft, startTop);
            geometry.EndPoint
= new Point(endLeft, endTop);
            p.Data
= geometry;
            p.Stroke
= brush;
            p.StrokeThickness
= 1;
            canvas1.Children.Add(p);
        }
        #endregion

 

  运行一下,如上图。

  之前没有使用递归的方法是只有这样的:

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.Shapes;

namespace SilverlightApplication2
{
    
public class Task
    {
        
public int ID { set; get; }
        
public int ParentID { set; get; }
        
public string Name { set; get; }
    }
    
public partial class MainPage : UserControl
    {
        
private static List<Task> listTask;
        
public MainPage()
        {
            InitializeComponent();
            listTask
= new List<Task>();
            listTask.Add(
new Task() { ID = 1, ParentID = 0, Name = "1" });
            listTask.Add(
new Task() { ID = 2, ParentID = 1, Name = "11" });
            listTask.Add(
new Task() { ID = 3, ParentID = 1, Name = "12" });
            listTask.Add(
new Task() { ID = 4, ParentID = 2, Name = "21" });
            listTask.Add(
new Task() { ID = 5, ParentID = 2, Name = "22" });
            listTask.Add(
new Task() { ID = 6, ParentID = 3, Name = "31" });
            listTask.Add(
new Task() { ID = 7, ParentID = 3, Name = "32" });
            listTask.Add(
new Task() { ID = 8, ParentID = 3, Name = "33" });
            listTask.Add(
new Task() { ID = 9, ParentID = 4, Name = "42" });
            listTask.Add(
new Task() { ID = 10, ParentID =4, Name = "42" });
            listTask.Add(
new Task() { ID = 11, ParentID =3, Name = "34" });
            listTask.Add(
new Task() { ID = 12, ParentID = 5, Name = "51" });
            listTask.Add(
new Task() { ID = 13, ParentID = 8, Name = "81" });
            this.Loaded
+= new RoutedEventHandler(MainPage_Loaded);
        }
        void MainPage_Loaded(
object sender, RoutedEventArgs e)
        {            
            AddAll();        
        }        
        class TaskPro
        {
            
public Task task { set; get; }
            
public double top { set; get; }
            
public double left { set; get; }
            
public int index { set; get; }
        }
        class TaskCount
        {
            
public double Top { set; get; }
            
public List<Task> Tasks { set; get; }
        }
        static List
<TaskPro> listTaskPro = new List<TaskPro>();
        static List
<TaskCount> listTopAndTasks = new List<TaskCount>();
        void AddAll()
        {
            foreach(Task t in listTask)
            {
                
if (t.ParentID == 0)
                {
                    listTaskPro.Add(
new TaskPro() { task = t, index = 1, left = this.canvas1.Width / 2, top = 0 });
                }
                
else
                {
                    
for(int i=0;i<listTaskPro.Count;i++)
                    {
                        
if (t.ParentID == listTaskPro[i].task.ID)
                        {
                            listTaskPro.Add(
new TaskPro() { task = t, top = listTaskPro[i].top + 80, index = 0, left = 0 });
                        }
                    }
                }
            }

            
#region 汇总层及层内的元素个数
            foreach (TaskPro t in listTaskPro)
            {
                bool IsExist
= false;
                foreach(TaskCount tc in listTopAndTasks)
                {
                    
if(tc.Top==t.top)
                    {
                        IsExist
= true;
                    }
                }
                
if(!IsExist)
                {
                    listTopAndTasks.Add(
new TaskCount() { Top=t.top, Tasks=new List<Task>() });
                }
                var topAndTasks
= listTopAndTasks.Where(m=>m.Top==t.top).FirstOrDefault();
                topAndTasks.Tasks.Add(t.task);              
            }
            #endregion

            foreach (TaskPro t in listTaskPro)
            {
                
for (int i = 0; i < listTopAndTasks.Count;i++ )
                {
                    
for (int j = 0; j < listTopAndTasks[i].Tasks.Count;j++ )
                    {
                        
if (listTopAndTasks[i].Tasks[j].ID == t.task.ID)
                        {
                            t.index
= j + 1;
                        }
                    }
                }
            }

            
for (int i = 0; i < listTaskPro.Count; i++)
            {
                
if (listTaskPro[i].task.ParentID == 0)
                {
                    listTaskPro[i].left
= this.canvas1.Width / 2;
                }
                
else
                {
                    var childCount
= listTaskPro.Where(m => m.task.ParentID == listTaskPro[i].task.ParentID).Count();
                    var parentLeft
= listTaskPro.Where(m => m.task.ID == listTaskPro[i].task.ParentID).FirstOrDefault().left;
                    var perLength
= parentLeft*1.5 / (childCount + 1);
                    listTaskPro[i].left
=listTaskPro[i].index*perLength;                                    
                }
            }
            foreach (TaskPro t in listTaskPro)
            {
                AddBtn(t.task.Name, t.left, t.top);
                
if(t.task.ParentID!=0)
                {
                    TaskPro tp
= listTaskPro.Where(m=>m.task.ID==t.task.ParentID).FirstOrDefault();
                    AddLine(tp.left
+buttonWidth/2, tp.top+buttonHeight, t.left+buttonWidth/2, t.top);
                }
            }
        }
        
double buttonHeight = 20;
        
double buttonWidth = 50;
        void AddBtn(
string content,double left,double top)
        {
            Button btn
= new Button();
            btn.Content
= content;
            btn.Width
= buttonWidth;
            btn.Height
= buttonHeight;
            this.canvas1.Children.Add(btn);
            Canvas.SetLeft(btn,
left);
            Canvas.SetTop(btn, top);
        }

        void AddLine(
double startLeft,double startTop,double endLeft,double endTop)
        {
            Path p
= new Path();
            LineGeometry geometry
= new LineGeometry();
            SolidColorBrush brush
= new SolidColorBrush();            

            brush.Color
= Colors.Black;
            geometry.StartPoint
= new Point(startLeft, startTop);
            geometry.EndPoint
= new Point(endLeft, endTop);
            p.Data
= geometry;
            p.Stroke
= brush;
            p.StrokeThickness
= 1;

            canvas1.Children.Add(p);
        }
    }
}

0
相关文章