3

I have an ObservableCollection Bound to a WPF List View. I am looking to be able to sort the columns of the ListView control by clicking on the Column Header. To do this I am sorting the ObservableCollection and letting the binding take care of updating the GUI.

To sort the ObservableCollection I am using the following code:

sortedData = new ObservableCollection<Tag>( from x in data
                                            orderby x.ID descending
                                            select x );
data = sortedData;

NB: data is bound to the ListView

The problem I'm having is that for each of the columns there would be a lot of copy-paste code to achieve the desired effect. Is it possible to pass the 'orderby x.ID descending' portion of the LINQ statement as a function parameter?

Or is there an entirely easier way to achieve the desired result?

Rupesh Yadav
  • 12,096
  • 4
  • 53
  • 70
TK.
  • 46,577
  • 46
  • 119
  • 147

6 Answers6

3

You could use a Func as a method parameter containing a lambda expression.

If you want to order every single type by it's ID you could specify an interface on all of those types too and use a generic method.

For example

public ObservableCollection<Tag> Sort(Func<ObservableCollection<Tag>> sortFunc)  
{  
    //do something else  
    data = sortFunc();  
    //do something else  
}

which can be called like

Sort(list.OrderByDescending(x => x.ID));

in which list is your ObservableCollection.

Factor Mystic
  • 26,279
  • 16
  • 79
  • 95
thekip
  • 3,660
  • 2
  • 21
  • 41
3

You define a sort function like this:

Func<Tag, int> sortFunc = x => -x.ID;

(Sorting by negative ID has the same effect as sorting by ID descending.)

You can then apply this sort function to any IEnumerable<Tag>:

var sortedData = new ObservableCollection<Tag>(data.OrderBy(sortFunc));
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • Ah, that **int** in the **Func<>** was tripping me up... I was trying to put the collection type in there, such as **Func>** (which doesn't really make any sense at all) So the first arg is the type of the class in the collection, the second is the return type of the property in that class (That makes much more sense) Thanks for the tip on negative result to emulate descending as well – Josh Stribling Dec 20 '11 at 02:28
1

The way I managed to achieve this was with thekip's idea of passing a Func into the function e.g.

sortColumn( "ID", x => x.ID );

protected void sortColumn<T>( string name, Func<Tag, T> selector )
{
    ObservableCollection<Tag> sortedData = new ObservableCollection<Tag>( TagData.OrderBy( selector ) );

    data = sortedData;
}
TK.
  • 46,577
  • 46
  • 119
  • 147
0

You can use Dynamic Query.It will composing LINQ statements on the fly, dynamically, at run time.

For example:

var query =
           db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
           OrderBy("CompanyName").
           Select("New(CompanyName as Name, Phone)");

You can get it here: http://code.msdn.microsoft.com/DynamicQuery-f65f6a4d

pixparker
  • 2,903
  • 26
  • 23
0

I think you are looking for Dynamic Linq.

See if these sample helps :-

http://msdn.microsoft.com/en-gb/bb737920.aspx

http://msdn.microsoft.com/en-gb/bb737920.aspx

Deepesh
  • 5,346
  • 6
  • 30
  • 45
0

You can use Dynamic Linq for this

whith it you can write something like:

var sortExpr = "x.ID";

IQueryable<Tag> sortedQuery = query.OrderBy(sortExpr);

Vladimir
  • 2,082
  • 1
  • 13
  • 27