【IT168 技术文档】这两天遇到一个问题,项目中需要在silverlight中使用连接图的方式来显示任务之间的关系,总体有父子和平行两种,昨天在改同事的代码,一直出问题,索性晚上写了一下实现方法。
需求:
有一个List对象中存了若干个Task,这些Task对象通过ParentID属性进行关联,现在要求将这个List中的任务使用图的方式形成如父子关系和平行关系的图示例如下图:

实现方法思考
刚开始接到这个任务我就想着递归应该可以搞定了,但是仔细考虑才发现每个任务的子任务需要在一定区域内才行,需要计算子级和子级之间的距离,如果使用递归,例如上图的元素“12”的位置就没有办法很好确定了。
我决定将途中的节点抽象为一个类,这个类至少应该含有上边界top,左边届left及节点的名称等属性,然后从这个List对象中构造出每个节点的属性。
实现步骤
1,首先我们为图模拟一个数据源,注意其中的任务是通过ParentID关联的
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);
}
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);
}
2,然后我们为要生成的图中节点构造一个类
class TaskPro
{
public Task task { set; get; }
public double top { set; get; }
public double left { set; get; }
public int index { set; get; }//这是为了找到节点在某层的位置来计算left
}
{
public Task task { set; get; }
public double top { set; get; }
public double left { set; get; }
public int index { set; get; }//这是为了找到节点在某层的位置来计算left
}
3,使用递归将List中的数据做初步整理,存入一个List
void AddMethod(Task task)
{
if (task.ParentID == 0)
{
listOfTaskPro.Add(new TaskPro() { task = task, top = 0, index = 0, left = 0 });
}
else
{
var t=listTask.Where(m=>m.ID==task.ParentID).FirstOrDefault();
var tpro=listOfTaskPro.Where(m=>m.task.ID==t.ID).FirstOrDefault();
listOfTaskPro.Add(new TaskPro() { task=task, index=0, top=tpro.top+50, left=0 });
}
foreach (Task t in listTask.Where(m=>m.ParentID==task.ID).ToList())
{
AddMethod(t);
}
}
{
if (task.ParentID == 0)
{
listOfTaskPro.Add(new TaskPro() { task = task, top = 0, index = 0, left = 0 });
}
else
{
var t=listTask.Where(m=>m.ID==task.ParentID).FirstOrDefault();
var tpro=listOfTaskPro.Where(m=>m.task.ID==t.ID).FirstOrDefault();
listOfTaskPro.Add(new TaskPro() { task=task, index=0, top=tpro.top+50, left=0 });
}
foreach (Task t in listTask.Where(m=>m.ParentID==task.ID).ToList())
{
AddMethod(t);
}
}