对复合集合进行排序

时间:2008-08-14 16:30:50

标签: c# .net wpf data-binding collections

因此,WPF不支持CompositeCollections视图的标准排序或过滤行为,因此解决此问题的最佳做法是什么。

有两个或更多不同类型的对象集合。您希望将它们组合成单个可排序和可过滤的集合(必须手动实现排序或过滤)。

我考虑过的一种方法是创建一个只有少数核心属性的新对象集合,包括我希望对集合进行排序的属性,以及每种类型的对象实例。

class MyCompositeObject
{
    enum           ObjectType;
    DateTime       CreatedDate;
    string         SomeAttribute;
    myObjectType1  Obj1;
    myObjectType2  Obj2;
{
class MyCompositeObjects : List<MyCompositeObject> { }

然后遍历我的两个对象集合以构建新的复合集合。显然这是一种蛮力方法,但它会起作用。我将获得新的复合对象集合上的所有默认视图排序和过滤行为,并且我可以在其上放置数据模板以根据实际存储在该复合项目中的类型来正确显示列表项目。

有什么建议以更优雅的方式做到这一点?

3 个答案:

答案 0 :(得分:1)

你提到的“蛮力”方法实际上是理想的解决方案。请注意,所有对象都在RAM中,没有I / O瓶颈,因此您可以在任何现代计算机上在不到一秒的时间内对数百万个对象进行排序和过滤。

使用集合的最佳方式是.NET 3.5中的System.Linq命名空间

  

谢谢 - 我也考虑过LINQ   对象,但我担心有损失   键入数据的灵活性   模板,我需要显示   我列表中的对象。

如果您现在无法预测人们将如何对对象集合进行排序和过滤,那么您应该查看 System.Linq.Expressions 名称空间,以便在运行时根据需要构建lambda表达式(首先,让用户构建表达式,然后编译,运行,最后使用反射命名空间来枚举结果)。围绕它而言更为棘手,但是非常宝贵的功能,可能(最终确定)比LINQ本身更具突破性的功能。

答案 1 :(得分:1)

更新:我找到了一个更优雅的解决方案:

class MyCompositeObject
{
    DateTime    CreatedDate;
    string      SomeAttribute;
    Object      Obj1;
{
class MyCompositeObjects : List<MyCompositeObject> { }

我发现由于反射,存储在Obj1中的特定类型在运行时被解析,并且特定类型的DataTemplate按预期应用!

答案 2 :(得分:1)

我对WPF还不是很熟悉,但我认为这是关于排序和过滤List<T>集合的问题。

  

(必须手动实施排序或过滤)

您是否会重新考虑实施自己的排序或过滤功能?根据我的经验,它很容易使用。下面的示例使用匿名委托,但您可以轻松定义自己的方法或类来实现复杂的排序或过滤。这样的类甚至可以具有配置和更改排序和动态过滤的属性。

List<T>.Sort(Comparison<T> comparison)与自定义比较功能一起使用:

// Sort according to the value of SomeAttribute
List<MyCompositeObject> myList = ...;
myList.Sort(delegate(MyCompositeObject a, MyCompositeObject b) 
{
    // return -1 if a < b
    // return 0 if a == b
    // return 1 if a > b
    return a.SomeAttribute.CompareTo(b.SomeAttribute);
};

从列表中获取项目子集合的类似方法。

List<T>.FindAll(Predicate<T> match)与自定义过滤器功能结合使用:

// Select all objects where myObjectType1 and myObjectType2 are not null
myList.FindAll(delegate(MyCompositeObject a)
{
    // return true to include 'a' in the sub-collection
    return (a.myObjectType1 != null) && (a.myObjectType2 != null);
}