对复合集合进行排序

7
因为WPF不支持对CompositeCollections视图进行标准的排序或过滤行为,所以解决这个问题的最佳实践是什么?
有两个或更多不同类型的对象集合。您想将它们组合成一个可排序和可过滤的单一集合(而无需手动实现排序或过滤)。
我考虑的方法之一是创建一个新的对象集合,只包括少数核心属性,包括我想要按其排序的属性,以及每种类型的一个对象实例。
class MyCompositeObject
{
    enum           ObjectType;
    DateTime       CreatedDate;
    string         SomeAttribute;
    myObjectType1  Obj1;
    myObjectType2  Obj2;
{
class MyCompositeObjects : List<MyCompositeObject> { }

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

有没有更优雅的方法来做到这一点?

3个回答

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.FindAll(Predicate 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);
}

Brian:一旦MyCompositeObject被构建,作为ICollectionView的一部分,我可以免费获得排序和过滤功能。问题的关键在于处理不同对象类型的集合并将它们视为一个集合。组合集合是创建集合的答案,但不是排序和过滤的答案。 - Christopher Scott

1

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

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

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


1
你提到的“暴力”方法实际上是理想的解决方案。请注意,所有对象都在RAM中,没有I/O瓶颈,因此您可以在任何现代计算机上在不到一秒钟的时间内对数百万个对象进行排序和过滤。
与集合一起工作的最优雅的方式是.NET 3.5中的System.Linq命名空间。
谢谢 - 我也考虑过使用LINQ来处理对象,但我担心会失去针对类型数据模板的灵活性,而我需要使用这些模板来显示我的列表中的对象。
如果您无法预测人们将如何对对象集合进行排序和过滤,则应查看System.Linq.Expressions命名空间,在运行时构建您的lambda表达式(首先让用户构建表达式,然后编译,运行并最终使用反射命名空间枚举结果)。这更加棘手,但是它是一个非常有价值的功能,可能(对我来说肯定)甚至比LINQ本身更具突破性的功能。

lubos: 谢谢 - 我也考虑过使用LINQ操作对象,但我的担忧在于会损失类型数据模板的灵活性,而我需要这些模板来显示列表中的对象。 - Christopher Scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接