Edit 2019-01-31: Latest solution
I've followed examples here and here to create a generic sort with memberexpressions, but I can't figure out how I'm supposed to add a "ThenBy" clause, or combine multiple columns for sorting in the methodcallexpression. Ideally, the ThenBy should go before skip, but it can't because it can't see the orderby clause that I made with the methodcallexpression. GridSortExpression is a Telerik class - it just describes which column and direction the query should be sorted.
Can anyone shed some light? Here is what I have right now:
Dim exp As Expressions.Expression(Of Func(Of Product_Catalog, Boolean)) = PredicateBuilder.True(Of Product_Catalog)()
exp = exp.And(Function(e) e.Chapter_Price > 30)
Dim sortExpression As New List(Of GridSortExpression)({New GridSortExpression() With {.SortOrder = GridSortOrder.Descending, .FieldName = "Id"}})
If sortExpression.Count = 0 Then
     catalogList = con.Product_Catalogs.AsExpandable.Where(exp).OrderBy(Function(o) o.Item_Type).ThenBy(Function(o) o.Item_Description).Skip(startRowIndex).Take(maximumRows).ToList
Else
     Dim param As ParameterExpression = Expression.Parameter(GetType(Product_Catalog), String.Empty)
     Dim prop As MemberExpression = Expression.PropertyOrField(param, sortExpression(0).FieldName)
     Dim sort As LambdaExpression = Expression.Lambda(prop, param)
     Dim source = con.Product_Catalogs.AsExpandable.Where(exp)
     Dim resultExp As MethodCallExpression
     resultExp = Expression.[Call](GetType(Queryable), "OrderBy" & If(sortExpression(0).SortOrder = GridSortOrder.Descending, "Descending", ""), _
         New Type() {GetType(Product_Catalog), prop.Type}, con.Product_Catalogs.AsExpandable.Where(exp).Expression, Expression.Quote(sort))
     catalogList = source.Provider.CreateQuery(Of Product_Catalog)(resultExp).Skip(startRowIndex).Take(maximumRows).ToList
End If
Here is a very generic way to do property sorting without having to implement multiple sort comparers for each slightly different sort.
it will allow any number of sort "Columns" (though you would need to enhance slightly to support different sort directions)
The drawback is it's obviously not the most efficient, though the use of invoking delegates is far more efficient then using reflection. You also need to define a general function of the properties of the objects that you may want to sort by. By making it more object specific you may be able to fix that aspect...
Public Class PropertySortComparer
Implements IComparer
Public Delegate Function GetProp(ByVal obj As Object) As Object
Public SortProps As New List(Of GetProp)
Public Sub New(ParamArray SortMethods() As GetProp)
    Me.SortProps.AddRange(SortMethods)
End Sub
Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
    For Each gp As GetProp In SortProps
        Dim xVal As Object = gp.Invoke(x)
        Dim yVal As Object = gp.Invoke(y)
        If xVal > yVal Then
            Return 1
        ElseIf xVal < yVal Then
            Return -1
        Else
            'next loop does next property
        End If
    Next
    Return 0
End Function
End Class
Public Module module1
Sub test()
    Dim buffer As New List(Of Rectangle)
    buffer.Add(New Rectangle(34, 55, 40, 30))
    buffer.Add(New Rectangle(34, 55, 45, 38))
    buffer.Add(New Rectangle(34, 56, 46, 30))
    buffer.Add(New Rectangle(34, 70, 45, 30))
    Dim Lst() As Rectangle = buffer.ToArray
    Array.Sort(Lst, New PropertySortComparer(AddressOf Left, AddressOf Top, AddressOf Widht))
    'Lst is now sorted by Left, Top, Width
End Sub
Public Function Left(r As Object) As Object
    Return r.Left
End Function
Public Function Top(r As Object) As Object
    Return r.Top
End Function
Public Function Widht(r As Object) As Object
    Return r.Width
End Function
End Module
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With