对复合集合进行排序

时间:2020-03-05 18:39:40  来源:igfitidea点击:

因此WPF不支持CompositeCollections视图的标准排序或者筛选行为,因此解决此问题的最佳实践是什么。

有两个或者多个不同类型的对象集合。我们希望将它们组合成单个可排序和可过滤的集合(无需手动实现排序或者过滤器)。

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

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

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

对于以更优雅的方式执行此操作有什么建议?

解决方案

回答

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

使用集合的最优雅的方法是.NET 3.5中的System.Linq命名空间

Thanks - I also considered LINQ to
  objects, but my concern there is loss
  of flexibility for typed data
  templates, which I need to display the
  objects in my list.

如果我们目前无法预测人们将如何对对象集合进行排序和过滤,则应查看System.Linq.Expressions命名空间以在运行时按需构建Lambda表达式(首先让用户构建表达式,然后进行编译,运行,最后使用反射名称空间枚举结果。将脑袋绕在它上面是比较棘手的,但它是非常宝贵的功能,可能(对我而言)比LINQ本身更具突破性。

回答

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

(withing having to manually implement sort or filter)

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

使用`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 &lt;T> .FindAll(Predicate &lt;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);
}

回答

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

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

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