我有以下简化类:
public class BaseContainer
{
public BaseContainer()
{
Children = new ObservableCollection<BaseContainer>();
}
public ObservableCollection<BaseContainer> Children { get; set; }
}
public class ItemA : BaseContainer
{
public ItemA()
{
base.Children.Add(new ItemB() { ItemBName = "bb" });
base.Children.Add(new ItemA() { ItemAName = "ab" });
base.Children.Add(new ItemB() { ItemBName = "ba" });
base.Children.Add(new ItemA() { ItemAName = "aa" });
}
public string ItemAName { get; set; }
}
public class ItemB : BaseContainer
{
public string ItemBName { get; set; }
}
我正在尝试根据两个条件对ItemA.Children集合进行排序:
所以在排序之后我会期待这样的事情:
关于如何实现这一目标的任何想法?
我能够按类类型名称排序:
List<BaseContainer> temp = base.Children.ToList();
temp.Sort((x, y) => string.Compare(x.GetType().Name, y.GetType().Name));
base.Children.Clear();
base.Children.AddRange(temp);
但是姓名没有排序......
谢谢!
答案 0 :(得分:2)
var result = temp.OrderBy(x => x.GetType().Name).ThenBy(x => GetPropValue(x));
string GetPropValue(object o)
{
Type t = o.GetType();
var p = t.GetProperty("ItemAName");
if (p != null)
{
return (string)p.GetValue(o, null);
}
p = t.GetProperty("ItemBName");
return (string)p.GetValue(o, null);
}
答案 1 :(得分:1)
这将获得所有的A,由AName命令它们,然后连接所有按B名称排序的B.
var result = Children.OfType<ItemA>().OrderBy(a => a.ItemAName).Cast<Base>()
.Concat(Children.OfType<ItemB>().OrderBy(b => b.ItemBName));
我不确定这是我要使用的设计......您可以考虑在基类中添加一些东西来促进这种排序。
答案 2 :(得分:1)
您可以通过指定ItemName
来初始化项目,但BaseContainer
,ItemA
和ItemB
都不会定义此类属性。
声明ItemName in the base class
BaseContainer`。 item类自动继承此属性,无需在那里重新定义这样的字段。
public class BaseContainer
{
public string ItemName { get; set; }
...
}
public class ItemA : BaseContainer
{
// Inherits ItemName
}
public class ItemB : BaseContainer
{
// Inherits ItemName
}
现在按如下方式对列表进行排序:
var result = base.Children
.OrderBy(b => b.GetType().Name)
.ThenBy(b => b.ItemName);
在排序之前无需将其存储到临时列表中。结果是IEnumerable<BaseContainer>
。如果要将结果存储为列表,可以附加.ToList()
。
var result = base.Children
.OrderBy(b => b.GetType().Name)
.ThenBy(b => b.ItemName)
.ToList();
<强>更新强>
根据您的评论,您没有共同的ItemName
财产。 为什么?你真的应该有一个。重构你的课程。如果由于某种原因您不想在ItemName
中使用BaseContainer
,请创建抽象基类Item
或让项目实现公共接口。
public abstract class Item : BaseContainer
{
public string ItemName { get; set; }
}
public class ItemA : Item
{
}
public class ItemB : Item
{
}
或者
public interface IItem
{
string ItemName { get; set; }
}
public class ItemA : BaseContainer, IItem
{
public string ItemName { get; set; }
}
public class ItemB : BaseContainer, IItem
{
public string ItemName { get; set; }
}
现在你可以像这样排序
var result = base.Children
.OfType<Item> // or .OfType<IItem>
.OrderBy(i => i.GetType().Name)
.ThenBy(i => i.ItemName);
,结果将是IEnumerable<Item>
或IEnumerable<IItem>
。
另一个选择是覆盖每个对象从ToString
继承的Syste.Object
方法。
public class ItemA : BaseContainer
{
public string ItemAName { get; set; }
public override string ToString()
{
return "ItemA: " + ItemAName;
}
}
这简化了排序,因为两个条件(按类型排序和按名称排序)可以一步完成。此字符串也将显示在列表框,组合框等中。
var result = base.Children
.OrderBy(b => b.ToString());
如果无法做到这一点,请为此目的创建并实现一个接口:
public interface ISortable
{
string SortString { get; }
}
public class ItemA : BaseContainer, ISortable
{
public string ItemAName { get; set; }
public string SortString { get { return "ItemA: " + ItemAName; } }
}
并按
排序var result = base.Children
.OfType<ISortable>
.OrderBy(b => b.SortString);