Rohan Sampat
Rohan Sampat

Reputation: 970

Sort an observable collection of type T where T will change on run time (generics)

Hello I want to sort an ObservableCollection but I cant get access to its properties.

public static class CommonMethods<T> 
{
    public static ObservableCollection<T> Sort(ObservableCollection<T> array, string columnName, bool sort) 
    {
        ObservableCollection<T> res = new ObservableCollection<T>();
        res = res.OrderBy(r => r[""]) // This gives an error says cannot apply indexing with [] to an expression of type T.
        return res;
    }
}

The Calling code.

mlRegionDetails = CommonMethods<MLRegion>.Sort(mlRegionDetails, columnName, sort);

Please do tell me where I m going wrong.

Upvotes: 0

Views: 246

Answers (2)

Rohan Sampat
Rohan Sampat

Reputation: 970

At last i found an alternate solution to the problem. I create a temp var then convert that ObservableCollection to AsEnumerable and ordering it by the Key passed to it.

Creating key part credit goes to @Camilo Terevinto

public static class CommonMethods
{
    public static ObservableCollection<T> sort<T>(ObservableCollection<T> array, Func<T, object> key)
    {
        var res = array.AsEnumerable().OrderByDescending(key); ;
        ObservableCollection<T> temp = new ObservableCollection<T>(res);
        return temp;
    }
}

Upvotes: 0

Camilo Terevinto
Camilo Terevinto

Reputation: 32063

Instead of passing the name of the property you want to order by, pass the selector function:

public static ObservableCollection<T> Sort(ObservableCollection<T> array, Func<T, object> columnSelector, bool sort) 
{
    ObservableCollection<T> res = new ObservableCollection<T>(array.OrderBy(columnSelector));
    return res;
}

And call it using this:

mlRegionDetails = CommonMethods<MLRegion>.Sort(mlRegionDetails, x => x.SomeColumn, sort);

If you want to do this using strings, you will need to build the expression manually.

Note: the following code has not been tested as it was written here, it may need some change.

public static class CommonMethods<T> 
{
    private static readonly MethodInfo orderByMethod =
        typeof(Enumerable).GetMethods().Single(method =>
            method.Name == nameof(Enumerable.OrderBy) && method.GetParameters().Length == 2);

    public static ObservableCollection<T> Sort(ObservableCollection<T> array, string columnName, bool sort) 
    {
        var tType = typeof(T);
        var parameter = Expression.Parameter(tType);

        Expression member = Expression.Property(parameter, columnName);

        var lambda = Expression.Lambda(member, paramter);

        var genericMethod = orderByMethod.MakeGenericMethod(tType, member.Type);

        var orderedData = genericMethod.Invoke(null, new object[] { array, lambda }) as IEnumerable<T>;

        return new ObservableCollection<T>(orderedData);
    }
}

Upvotes: 2

Related Questions