【问题标题】:Sorting a composite collection对复合集合进行排序
【发布时间】:2008-08-14 16:30:49
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我对 WPF 还不是很熟悉,但我认为这是一个关于排序和过滤 List&lt;T&gt; 集合的问题。

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

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

    List&lt;T&gt;.Sort(Comparison&lt;T&gt; 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&gt;.FindAll(Predicate&lt;T&gt; 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 的一部分免费进行排序和过滤。问题的症结在于处理单独的对象类型集合并将它们视为一个集合。复合集合是创建集合的答案,但不是排序过滤。
    【解决方案2】:

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

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

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

    如果您目前无法预测人们将如何对您的对象集合进行排序和过滤,那么您应该查看 System.Linq.Expressions 命名空间,以便在运行时按需构建您的 lambda 表达式(首先让用户构建表达式,然后编译、运行,最后使用反射命名空间枚举结果)。将你的头脑围绕起来更加棘手,但它是无价的功能,可能(对我来说肯定)比 LINQ 本身更具突破性的功能。

    【讨论】:

    • lubos:谢谢 - 我也考虑过 LINQ to objects,但我担心类型化数据模板失去了灵活性,我需要在列表中显示对象。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-15
      • 2011-10-20
      • 1970-01-01
      • 2011-04-06
      • 2011-04-04
      • 2013-02-25
      • 2017-04-26
      相关资源
      最近更新 更多