我一直在使用ASP.NET中的一个页面。此页面的行为与论坛完全相同。用户可以回复条目。回复表示为ItemReply。当用户回复某个项目时,ParentID将设置为用户正在响应的ItemReply的ID。
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 :(得分:0)
出于某种原因,我的所有ItemReply元素的等级为1.什么 我做错了吗?
您的SetLevel
方法不正确,因为它依赖于特定的枚举顺序来确保其正确性 - 父母必须在其子女之前处理。不幸的是,没有任何迹象表明你所拥有的清单可以保证这样的订单。
如果项目的父级在调用SetLevel
时未设置其级别,该怎么办?然后,您的方法会分配Level
1 + 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
永远不会使用其父级别的未初始化值。