views:

293

answers:

3

I have an observable collection. I want to use linq to sort it. I have the propertyname of the property I want to sort (as a string) for my type.

What is the best/fastest way to do this?

Different propertyname strings will be passed into the function

+2  A: 

I have only ever been able to do this through reflection.

var v = YouList.OrderBy(t => t.GetType().InvokeMember(sField,
    System.Reflection.BindingFlags.GetProperty,
    null,
    t,
    null)
).ToList());

I'm assuming the same code will work for an ObservableCollection...

Nate Bross
This will call the GetProperty on each and every item in the list, which is gonna be costly. The least you can do is take the GetProperty out of the loop and save a local PropertyInfo variable.
Avish
+1  A: 

You should be able to construct an Expression from that property name and pass that to OrderBy:

public IEnumerable<MyData> orderByDynamic(IEnumerable<MyData> objects, string propertyName) 
{
    var parameterExpression = Expression.Parameter(typeof(MyData), "x");
    var orderByExpression = Expression.Lambda<Func<MyData, TypeOfProperty>>(
        Expression.Property(parameterExpression, propertyName),
        parameterExpression);  
    return objects.OrderBy(orderByExpression)
}

The problem is that you need to know the type of the property at compile time for this to work.

Avish
unfortunately I actually didn't know the property type at compile time
zachary
+1  A: 

You can do sorting by using lambdas. I copied what's in the internal class used by the DataGrid:

        IEnumerable<T> sortedList = _list.ToArray<T>();

        foreach (SortDescription sortDescription in SortDescriptions)
        {
            PropertyInfo propertyInfo = typeof(T).GetProperty(sortDescription.PropertyName);
            Func<T, object> keySelector = item => propertyInfo.GetValue(item, null);

            switch (sortDescription.Direction)
            {
                case ListSortDirection.Ascending:
                    sortedList = sortedList.OrderBy(keySelector);
                    break;
                case ListSortDirection.Descending:
                    sortedList = sortedList.OrderByDescending(keySelector);
                    break;
                default:
                    continue;
            }
        }

        T currentItem = _currentItem;

Works quite nicely and better than trying to find an IComparer.

R4cOON