2011-11-27 66 views
1

我一直在ASP.NET中處理頁面。這個頁面的行爲完全像一個論壇。用戶可以回覆條目。答覆表示爲ItemReply。當用戶回覆一個項目時,ParentID被設置爲用戶正在響應的ItemReply的ID。C#中元素層次結構中的排序問題

public class ItemReply 
{ 
    public Guid ID { get; set; }  
    public Guid? ParentID { get; set; } 
    public int Level { get; set; }  
    public string Remarks { get; set; }  
    public DateTime CreatedOn { get; set; }  
    public string CreatedBy { get; set; } 

    public ItemReply(DataRow row) 
    { 
     ID = GetGuidFromRow(row, "ID", 0); 
     ParentID = GetGuidFromRow(row, "ParentID", null); 
     Remarks = GetStringFromRow(row, "Remarks", string.Empty); 
     Level = 1; 

     CreatedOn = GetDateTimeFromRow(row, "CreatedOn", DateTime.UtcNow); 
     CreatedBy = GetStringFromRow(row, "CreatedBy", string.Empty); 
    } 
} 

public class ItemComparer : IComparer<ItemReply> 
{ 
    IDictionary<Guid, ItemReply> itemLookup; 
    public ReplyComparer(IEnumerable<ItemReply> list) 
    { 
     itemLookup = list.ToDictionary(item => item.ID); 
     foreach (var item in list) 
      SetLevel(item); 
    } 

    public int SetLevel(ItemReplyitem) 
    { 
     if (item.Level == 0 && item.ParentID.HasValue) 
      item.Level = 1 + itemLookup[item.ParentID.Value].Level; 
     return item.Level; 
    } 

    public int Compare(ItemReply x, ItemReply y) 
    { 
     // see if x is a child of y 
     while (x.Level > y.Level) 
     { 
      if (x.ParentID == y.ID) 
       return 1; 
      x = itemLookup[x.ParentID.Value]; 
     } 

     // see if y is a child of x 
     while (y.Level > x.Level) 
     { 
      if (y.ParentID == x.ID) 
       return -1; 
      y = itemLookup[y.ParentID.Value]; 
     } 

     // x and y are not parent-child, so find common ancestor 
     while (x.ParentID != y.ParentID) 
     { 
      if (x.ParentID.HasValue) 
       x = itemLookup[x.ParentID.Value]; 
      if (y.ParentID.HasValue) 
       y = itemLookup[y.ParentID.Value]; 
     } 

     // compare createDate of children of common ancestor 
     return x.CreatedOn.CompareTo(y.CreatedOn); 
    } 
} 

此代碼基本上是執行經:

List<ItemReply> replies = GetRepliesFromDataSource(); 
replies.Sort(new ReplyComparer(replies)); 

的順序和層次結構似乎正常工作。但是,SetLevel方法無法正常工作。 SetLevel的用途主要用於確定從UI角度縮進回覆的距離。爲了演示,想象下面的層次結構:

- Root 
-- Child 1 
--- Grandchild A 
--- Grandchild B 
-- Child 2  
--- Grandchild C 

由於某種原因,我的所有ItemReply元素的級別都是1.我做錯了什麼?

謝謝!

+0

'SetLevel()'方法代碼在哪裏? – sll

回答

0

出於某種原因,我的所有ItemReply元素都有一級1.什麼 我做錯了什麼?

SetLevel方法是不正確的,因爲它依賴一個特定的枚舉順序爲它的正確性上 - 家長一定要孩子之前被處理。不幸的是,沒有任何跡象表明你所在的列表可以保證這樣的訂單。

如果在調用SetLevel時某個項目的父級未設置其級別,該怎麼辦?然後你的方法將分配Level1 + 0而不是1 + Parent's Actual Level

這是很容易固定用遞歸調用:

public int SetLevel(ItemReply item) 
{ 
    if (item.Level == 0 && item.ParentID.HasValue) 
     item.Level = 1 + SetLevel(itemLookup[item.ParentID.Value]); 

    return item.Level; 
} 

這確保了SetLevel從未與其父的水平未初始化值的作品。