我有一个名为NavigationElement
的课程,看起来像这样
public class NavigationElement
{
public int Id { get; set; }
public string Title { get; set; }
public string Link { get; set; }
public int SortOrder { get; set; }
public bool Visible { get; set; }
public int? ParentId { get; set; }
public virtual ICollection<NavigationElement> Children { get; set; }
public virtual NavigationElement Parent { get; set; }
public NavigationElement()
{
Children = new List<NavigationElement>();
}
}
如您所见,该课程是自我引用的。从那时起,我正在创建一个带下拉的网站导航菜单(游戏中的层次结构)。
我在订购物品方面苦苦挣扎。我希望按SortOrder
属性排序顶级项目,但 下的所有内容,我想按Title
属性排序按字母顺序
这就是我到目前为止所做的原因。
var orderedModel = unorderedModel.OrderBy(x => x.SortOrder).ThenBy(x => x.Children.OrderBy(y => y.Title).ThenBy(z => z.Children.OrderBy(a => a.Title))).ToList();
unorderedModel
的类型为List<NavigationElementModel>
。
这是编译,但是在运行代码时出现错误。错误说:
至少有一个对象必须实现IComparable。
答案 0 :(得分:3)
您应该对所有子元素进行递归并对其进行排序。
有点像:var ordered = unorderedModel.OrderBy(x=>x.SortOrder).ToList();
ordered.ForEach(OrderChildren);
public void OrderChildren(NavigationElement el)
{
el.Children = el.Children.OrderBy(x => x.Title).ToList();
if (el.Children != null)
{
foreach (var c in el.Children)
{
OrderChildren(c);
}
}
}
答案 1 :(得分:0)
这样的事情怎么样?
public static class LinqExtension {
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector) {
if (source == null) throw new ArgumentNullException("source");
foreach (var i in source) {
yield return i;
var children = childrenSelector(i);
if (children == null) continue;
foreach (var child in SelectManyRecursive(children, childrenSelector)) {
yield return child;
}
}
}
}
var orderedModel = unorderedModel
.OrderBy(x => x.SortOrder)
.SelectMany(x => new[] { x }.Union(
x.Children.SelectManyRecursive(y => y.Children)
.OrderBy(y => y.Parent.Title) // considering hierarchy
.ThenBy(y => y.Title)
))
.ToList();
答案 2 :(得分:0)
我会根据您的情况使用Sort hierarchy with path and depth fields using Linq的方法。
首先,我对How to flatten tree via LINQ?的答案中的一般树遍历助手:
public static partial class TreeUtils
{
public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}
}
解决您的特定问题:
var orderedModel = unorderedModel.Where(item => item.Parent == null).OrderBy(item => item.SortOrder)
.Expand(item => item.Children != null && item.Children.Any() ? item.Children.OrderBy(child => child.Title) : null)
.ToList();