有一個List物件中存了若干個Task,這些Task物件通過ParentID屬性進行關聯,現在要求將這個List中的任務使用圖的方式形成如父子關係和平行關係的圖示例如下圖:

0S93S950-0  


實現方法思考

剛開始接到這個任務我就想著遞迴應該可以搞定了,但是仔細考慮才發現每個任務的子任務需要在一定區域內才行,需要計運算元級和子級之間的距離,如果使用遞迴,例如上圖的元素「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); 
        }





2,然後我們為要生成的圖中節點構造一個類

 


class TaskPro 
        { 
            
public Task task { setget; } 
            
public double top { setget; } 
            
public double left { setget; } 
            
public int index { setget; }//這是為了找到節點在某層的位置來計算left

}




3,使用遞迴將List中的資料做初步整理,存入一個List<TaskPro>中,此時節點物件將具備top屬性,上邊距搞定。

 


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

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].
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()