How to sort a List Of Orders using a property

I have a gridview and recently added a new column for rowNo

<asp:TemplateField HeaderText="RowNo" ItemStyle-HorizontalAlign="left">
    <ItemTemplate>
        <asp:Literal ID="lblRowNo" runat="Server"></asp:Literal>
    </ItemTemplate>
</asp:TemplateField>

Open in new window


And on the rowDataBound event:

            Dim orderList As Order
            orderList = New Order()
            orderList.rowNo = e.Row.RowIndex + 1
            DirectCast(e.Row.FindControl("lblRowNo"), Literal).Text = orderList.rowNo

Open in new window


I need to be able to sort by this column, just like I am able to do in the other columns.

I added a property to my Order object, the name is _rowNo:
'Row No
Public _rowNo As Integer
Public Property rowNo As Integer
    Get
        Return _rowNo
    End Get
    Set(ByVal value As Integer)
        _rowNo = value
    End Set
End Property

Open in new window


Then I call the method SortByRowNo from the sorting event:
Protected Sub gdvHeaders_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gdvHeaders.Sorting
    Me.GetOrders()
    Dim temporders As System.Collections.Generic.List(Of Order) = DirectCast(Me.gdvHeaders.DataSource, List(Of Order))
    Dim storedsortdir As String = ViewState("sortdir")
    Dim dir As New SortDirection
    ViewState("sortdir") = storedsortdir
    If Not temporders Is Nothing Then
        Dim query As IQueryable = Nothing
        query = temporders.AsQueryable.OrderBy(e.SortExpression + " " + ConvertSortDirectionToSql(dir))
        If e.SortExpression = "rowNo" Then
            Dim SortedList As List(Of Order) = SortByRowNo(ConvertSortDirectionToSql(dir), e.SortExpression, temporders)
            Me.gdvHeaders.DataSource = SortedList
            Me.gdvHeaders.DataBind()
        Else
            Me.gdvHeaders.DataSource = query
            Me.gdvHeaders.DataBind()
        End If
    End 

Open in new window


The 2 methods:

Public Function SortByRowNo(Of Order)(sortDirection As String, sortExpression As String, order_data As List(Of Order)) As List(Of Order)
    Dim data_sorted As New List(Of Order)()
    If sortDirection = "ASC" Then
        data_sorted = (From n In order_data Order By GetDynamicSortProperty(n, sortExpression) Ascending).ToList()
    ElseIf sortDirection = "DESC" Then
        data_sorted = (From n In order_data Order By GetDynamicSortProperty(n, sortExpression) Descending).ToList()
    End If
    Return data_sorted
End Function

Public Function GetDynamicSortProperty(item As Object, propName As String) As Object
    'Use reflection to get order type
    Return item.[GetType]().GetProperty(propName).GetValue(item, Nothing)
End Function

Open in new window


But when I run the debugger, and the code runs to this line:

Return item.[GetType]().GetProperty(propName).GetValue(item, Nothing)

Open in new window


The rowNo property always has a zero as its value, and nothing happens, clicking the RowNo column, does not sort the grid.


Can someone please help me out to figure this out?

I appreciate any help.

Many thanks.
the_lone_noteAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

the_lone_noteAuthor Commented:
I also tried this code:
   If e.SortExpression = "rowNo" And ConvertSortDirectionToSql(dir) = "DESC" Then
       temporders.Reverse()
       Me.gdvHeaders.DataSource = temporders
       Me.gdvHeaders.DataBind()
   Else
       Me.gdvHeaders.DataSource = query
       Me.gdvHeaders.DataBind()
   End If

Open in new window


It reverses the List, but the numbers always display 1, 2, 3, 4... whether ASC or DESC
CodeCruiserCommented:
What happens if you just change following code

        If e.SortExpression = "rowNo" Then
            Dim SortedList As List(Of Order) = SortByRowNo(ConvertSortDirectionToSql(dir), e.SortExpression, temporders)
            Me.gdvHeaders.DataSource = SortedList
            Me.gdvHeaders.DataBind()
        Else
            Me.gdvHeaders.DataSource = query
            Me.gdvHeaders.DataBind()
        End If

to

            Me.gdvHeaders.DataSource = query
            Me.gdvHeaders.DataBind()
the_lone_noteAuthor Commented:
Hi CodeCruiser,

I made the changed you suggested, and ran the code. When I click the RowNo header and the sorting event gets fired, I can see that the query contains the parameter rowNow as the sort by parameter, but the order of the row numbers does not change, it always displays 1,2,3,4,5...whether is asc or desc the sort by direction.
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

the_lone_noteAuthor Commented:
I made another change,

My Order property
    'Row No
    Public rowNoVal As Integer

    Public Property rowNo As Integer
        Get
            Return rowNoVal
        End Get
        Set(ByVal value As Integer)
            rowNoVal = value
        End Set
    End Property

Open in new window


Then I set it inside the Sorting event of the grid-view:

e.Row.DataItem.rowNo = e.Row.RowIndex + 1
DirectCast(e.Row.FindControl("lblRowNo"), Literal).Text = e.Row.DataItem.rowNo

Open in new window


When I run the code I can see that rowNo is getting the correct line number value, but the numbers are always displayed 1,2,3,4,5, although the sort changes.
the_lone_noteAuthor Commented:
I think I am close to get it right, it was a challenge just to figure out how to pass a value to the property other than 0 for each record, but something is still missing.

This shows by rowNo (asc):
RowNo   Created
1       5/29/2015 9:00:20 AM
2       5/29/2015 9:30:48 AM
3       5/29/2015 9:33:04 AM
4       5/29/2015 9:39:05 AM
5       5/29/2015 10:20:21 AM
6       5/29/2015 11:29:25 AM
7       5/29/2015 11:52:20 AM

Open in new window


And by rowNo (desc):
RowNo   Created
1       5/29/2015 11:52:20 AM
3       5/29/2015 10:20:21 AM
2       5/29/2015 11:29:25 AM
4       5/29/2015 9:39:05 AM
5       5/29/2015 9:33:04 AM
6       5/29/2015 9:30:48 AM
7       5/29/2015 9:00:20 AM

Open in new window


The orders are getting re-sorted by the sorting event, but the line numbers stay always in ascending order.

I am including the code for the Sorting event just in case changes needs to be made in there.

 Protected Sub gdvHeaders_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gdvHeaders.Sorting
    Me.GetOrders()
    Dim temporders As System.Collections.Generic.List(Of Order) = DirectCast(Me.gdvHeaders.DataSource, List(Of Order))
    Dim storedsortdir As String = ViewState("sortdir")
    Dim dir As New SortDirection
    If storedsortdir Is Nothing Then
        storedsortdir = "asc"
        dir = SortDirection.Ascending
        strSortDirection = ConvertSortDirectionToSql(SortDirection.Ascending)
    ElseIf storedsortdir = "asc" Then
        storedsortdir = "desc"
        dir = SortDirection.Descending
        strSortDirection = ConvertSortDirectionToSql(SortDirection.Descending)
    ElseIf storedsortdir = "desc" Then
        storedsortdir = "asc"
        dir = SortDirection.Ascending
        strSortDirection = ConvertSortDirectionToSql(SortDirection.Ascending)
    End If
    ViewState("sortdir") = storedsortdir
    If Not temporders Is Nothing Then
        Dim query As IQueryable = Nothing
        query = temporders.AsQueryable.OrderBy(e.SortExpression + " " + ConvertSortDirectionToSql(dir))
        Me.gdvHeaders.DataSource = query
        Me.gdvHeaders.DataBind()
    End If
End Sub

Open in new window


Thank you for your help!
CodeCruiserCommented:
You are generating the row number dynamically when the grid is being data bound so you are not sorting the rowno column itself. You need to add RowNo property to class itself and bind it to a grid column (instead of using a literal control).

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
the_lone_noteAuthor Commented:
Thank you CodeCruiser.

I did added the property rowNo to my Public Class Order, I posted the code for the property above.

What I do not understand is how to bind the property to the grid instead of using a literal control.

Do I need to change this part:
                    <ItemTemplate>
                        <asp:Literal ID="lblRowNo" runat="Server"></asp:Literal>                        
                    </ItemTemplate>

Open in new window

the_lone_noteAuthor Commented:
would you be willing to show me an example of how to do this? Thanks
CodeCruiserCommented:
Bind it just like you bind the other properties. I have not seen the full grid markup.
the_lone_noteAuthor Commented:
This is the gridview markup:

<asp:GridView
            EnableViewState="false"
            ID="gdvHeaders"
            runat="Server"
            AutoGenerateColumns="false"
            Visible="false"
            AllowSorting="true">
            <AlternatingRowStyle CssClass="tableAlt"></AlternatingRowStyle>
            <Columns>
                <asp:TemplateField HeaderText="RowNo" SortExpression="rowNo" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblRowNo" runat="Server"></asp:Literal>
                    </ItemTemplate>
                </asp:TemplateField>

Open in new window


Many thanks.
CodeCruiserCommented:
You only have one column in grid?
the_lone_noteAuthor Commented:
No, I just posted enough to show the column I am struggling with, but here is a copy of the full gridview mark-up:

<asp:GridView
            EnableViewState="false"
            ID="gdvHeaders"
            runat="Server"
            AutoGenerateColumns="false"
            Visible="false"
            CssClass="tableWhole"
            RowStyle-CssClass="tableRow"
            AlternatingRowStyle-CssClass="tableAlt"
            AllowSorting="true"
            HeaderStyle-CssClass="tableHeader"            
            UseAccessibleHeaderText="true">
            <AlternatingRowStyle CssClass="tableAlt"></AlternatingRowStyle>
            <Columns>
                <asp:TemplateField HeaderText="RowNo" SortExpression="rowNo" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblRowNo" runat="Server"></asp:Literal>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="E-Mail" SortExpression="Customer.email" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblEmail" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Order ID" SortExpression="orderId" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:HyperLink ID="lblOrderID" runat="Server"></asp:HyperLink>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="First" SortExpression="Soldaddress.First" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblFirst" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Last" SortExpression="Soldaddress.Last" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblLast" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Created" SortExpression="created" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblCreated" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Total" SortExpression="total" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblTotal" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="AX Order No." SortExpression="CRMOrderID" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblPSOrderNo" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Processed" SortExpression="CRMStatus" ItemStyle-HorizontalAlign="left">
                    <ItemTemplate>
                        <asp:Literal ID="lblProcessed" runat="Server"></asp:Literal>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Left"></ItemStyle>
                </asp:TemplateField>
            </Columns>
            <HeaderStyle CssClass="tableHeader"></HeaderStyle>
            <RowStyle CssClass="tableRow"></RowStyle>
        </asp:GridView>

Open in new window

the_lone_noteAuthor Commented:
Would you show me, how can I avoid overwriting previous rowNo values by assigning the row number value before doing initial binding of grid-view?
CodeCruiserCommented:
I don't understand how you are binding this grid. Are you doing that in code behind?

Any reason for not using bound field?

https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.boundfield(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
the_lone_noteAuthor Commented:
The grid-view was already designed when I added this new column, changing it will requires to make many other changes to how the code right now works.

I was able to make it work, this is what I did:

1. Added for loop to the GetOrders() routine, so each order will then have its own row number to later be able to use it just like any other property
    Dim i As Integer
    i = 1
    For Each order As Order In orderList.Items
        order.rowNo = i
        i += 1
    Next
    Me.gdvHeaders.Visible = True
    Me.gdvHeaders.DataSource = orderList.Items
    Me.gdvHeaders.DataBind()

Open in new window

2. Removed the incremental and assignment of rowNo from the grid-view's data-bound event:
    'Add rowNo
    e.Row.DataItem.rowNo = e.Row.RowIndex + 1
    DirectCast(e.Row.FindControl("lblRowNo"), Literal).Text = e.Row.DataItem.rowNo

Open in new window

3. Replaced #2 with:
    DirectCast(e.Row.FindControl("lblRowNo"), Literal).Text = e.Row.DataItem.rowNo

Open in new window

Now I can sort ASC|DESC using the rowNo column.
CodeCruiserCommented:
Good job
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.