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