views:

2013

answers:

5

So WPF doesn't support standard sorting or filtering behavior for views of CompositeCollections, so what would be a best practice for solving tihs problem.

There are two or more object collections of different types. You want to combine them into a single sortable and filterable collection (withing having to manually implement sort or filter).

One of the approaches I've considered is to create a new object collection with only a few core properties, including the ones that I would want the collection sorted on, and an object instance of each type.

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

And then loop through my two object collectiosn to build the new composite collection. Obviously this is a bit of a brute force method, but it would work. I'd get all the default view sorting and filtering behavior on my new composite object collection, and I'd be able to put a data template on it to display my list items properly depending on which type is actually stored in that composite item.

What suggestions are there for doing this in a more elegant way?

A: 

"Brute force" method you mention is actually ideal solution. Mind you, all objects are in RAM, there is no I/O bottleneck, so you can pretty much sort and filter millions of objects in less than a second on any modern computer.

The most elegant way to work with collections is System.Linq namespace in .NET 3.5

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.

If you can't predict at this moment how people will sort and filter your object collection, then you should look at System.Linq.Expressions namespace to build your lambda expressions on demand during runtime (first you let user to build expression, then compile, run and at the end you use reflection namespace to enumerate through results). It's more tricky to wrap your head around it but invaluable feature, probably (to me definitively) even more ground-breaking feature than LINQ itself.

lubos hasko
lubos: 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.
Christopher Scott
A: 

Have you looked at CollectionViewSource and ICollectionView? With those classes, you're able to customize grouping, sorting and filtering. I'm not sure if it applies to CompositeCollections, though.

ageektrapped
Have you ever tried? I tried and failed.Would love to see some code or links, anything.
Shimmy
ageektrapped: No, it doesn't which is the problem.
Christopher Scott
A: 

I'm not yet very familiar with WPF but I see this as a question about sorting and filtering List<T> collections.

(withing having to manually implement sort or filter)

Would you reconsider implementing your own sort or filter functions? In my experience it is easy to use. The examples below use an anonymous delegate but you could easily define your own method or a class to implement a complex sort or filter. Such a class could even have properties to configure and change the sort and filter dynamically.

Use List<T>.Sort(Comparison<T> comparison) with your custom compare function:

// 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);
};

A similar approach for getting a sub-collection of items from the list.

Use List<T>.FindAll(Predicate<T> match) with your custom filter function:

// 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 Ensink
Brian: Once MyCompositeObject is built, I get sorting and filtering for free as part of an ICollectionView.. The crux of the problem is dealing with the separate object type collections and treating them as one collection. Composite collections are the answer for creating the collection, but not the sorting filtering.
Christopher Scott
+1  A: 

Update: I found a much more elegant solution:

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

I found that due to reflection, the specific type stored in Obj1 is resolved at runtime and the type specific DataTemplate is applied as expected!

Christopher Scott
A: 

itowlson answers a simple and powerful answer that solves all your pain. take a look and vote on his answer.

Shimmy
From the answer itself:"Regarding filtering, sorting and grouping, as per Aron's answer these are not available on a view over a CompositeCollection."the accepted answer above works perfectly without all the Composite Collection fuss.
Christopher Scott
Nevermind do whatever works best for you.There are sometimes cases that you do want to use a CompositeCollection and sort it out.
Shimmy