Fixed header gridview with sorting functionality
Asked Answered
C

2

6

I've been trying to implement a gridview that has a fixed header when you scroll, but also allows for sorting when you click header columns. After searching for a while, I found a great solution online which works perfectly on my site. If you have the same question, check it out here - http://www.aspsnippets.com/Articles/Scrollable-GridView-with-Fixed-Headers-and-Client-Side-Sorting-using-jQuery-in-ASP.Net.aspx

Ignore the example on the page, it didn't work when I tried to sort it but it was functional when I put it on my own page.

Here is my question: I was hoping to be able to sort by multiple columns in conjunction, and the code on the site only allows for sorting on a single column. Does anyone have suggestions on how to add a second level of sorting?

Here is my code:

    <script type = "text/javascript">
    $(document).ready(function () {
        $("#<%=ChangedUPCs2.ClientID%>").tablesorter();
        SetDefaultSortOrder();
    });

    function Sort(cell, sortOrder) {
        var sorting = [[cell.cellIndex, sortOrder]];
        $("#<%=ChangedUPCs2.ClientID%>").trigger("sorton", [sorting]);
        if (sortOrder == 0) {
            sortOrder = 1;
            cell.className = "sortDesc";
        }
        else {
            sortOrder = 0;
            cell.className = "sortAsc";
        }
        cell.setAttribute("onclick", "Sort(this, " + sortOrder + ")");
        cell.onclick = function () { Sort(this, sortOrder); };
        document.getElementById("container").scrollTop = 0;
    }

    function SetDefaultSortOrder() {
        var gvHeader = document.getElementById("dummyHeader");
        var headers = gvHeader.getElementsByTagName("TH");
        for (var i = 0; i < headers.length; i++) {
            headers[i].setAttribute("onclick", "Sort(this, 1)");
            headers[i].onclick = function () { Sort(this, 1); };
            headers[i].className = "sortDesc";
        }
    }

<table id="dummyHeader" cellspacing="0" rules="all" border="1" style="width: 800px; border-collapse:collapse;" class = "grid">
            <thead>
            <tr>
                <th scope="col" style="width: 30px;">Tier</th>
                <th scope="col" style="width: 75px;">UPC</th>
                <th scope="col" style="width: 50px;">Line Code</th>
                <th scope="col" style="width: 100px;">Brand</th>
                <th scope="col" style="width: 205px;">Product</th>
                <th scope="col" style="width: 70px;">Old Qty / Old Price</th>                    
                <th scope="col" style="width: 70px;">New Qty / New Price</th>

                <th scope="col" style="width: 50px;">Cost</th>
                <th scope="col" style="width: 50px;">Old Margin</th>
                <th scope="col" style="width: 50px;">New Margin</th>
                <th scope="col" style="width: 50px;">Tag Type</th>
                <th scope="col" style="width: 50px;">Effective Date</th>
            </tr>
            </thead>
        </table>

        <div id="container" style="height:200px; overflow: auto; width: 817px;">
                 <asp:GridView ID="ChangedUPCs2" runat="server" AutoGenerateColumns="False" 
                    DataKeyNames="banner,enterprise_zone,UPC,ProductDescriptionLong"
                    DataSourceID="Changes2" class="styleGrid"  ondatabound="ChangedUPCs2GridDataBound" 
                     Width = "800px" ViewStateMode = "Disabled">
                     <Columns>
                        <asp:TemplateField HeaderText="Tier" ItemStyle-Width="30px">
                            <ItemTemplate>
                                <asp:Label ID="Tier" Text='<%# Eval("enterprise_zone") %>' runat="server" class="zn"/>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:BoundField DataField="UPC" HeaderText="UPC" ItemStyle-Width="75px" >
                        </asp:BoundField>
                        <asp:BoundField DataField="line_code" HeaderText="Line Code" ItemStyle-Width="50px" >
                        </asp:BoundField>
                        <asp:BoundField DataField="BrandName" HeaderText="Brand" 
                            ItemStyle-Width="100px" >
                        </asp:BoundField>
                        <asp:BoundField DataField="ProductDescriptionLong" HeaderText="Product" 
                            ItemStyle-Width="205px">
                        </asp:BoundField>
                        <asp:TemplateField HeaderText="Old Qty / Old Price">
                            <ItemTemplate>
                                <asp:Label ID="Label1" runat="server" Text='<%# Bind("ttlqty", "{0:N0}") %>'></asp:Label>
                                <asp:Label ID="Label2" runat="server" Text=" / "></asp:Label>
                                <asp:Label ID="Label3" runat="server" Text='<%# Bind("ttlretailprice", "{0:c}") %>'></asp:Label>
                            </ItemTemplate>
                            <EditItemTemplate>
                                <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("ttlqty") %>'></asp:TextBox>
                                <asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("ttlretailprice") %>'></asp:TextBox>
                            </EditItemTemplate>
                            <ItemStyle Width="70px" />
                        </asp:TemplateField>
                       <asp:TemplateField HeaderText="New Qty / New Price">
                            <ItemTemplate>
                                <asp:Label ID="Label7" runat="server" Text='<%# Bind("new_base_qty", "{0:N0}") %>'></asp:Label>
                                <asp:Label ID="Label8" runat="server" Text=" / "></asp:Label>
                                <asp:Label ID="Label9" runat="server" Text='<%# Bind("new_base_retail", "{0:c}") %>'></asp:Label>
                            </ItemTemplate>
                            <EditItemTemplate>
                                <asp:TextBox ID="TextBox7" runat="server" Text='<%# Bind("new_base_qty") %>'></asp:TextBox>
                                <asp:TextBox ID="TextBox9" runat="server" Text='<%# Bind("new_base_retail") %>'></asp:TextBox>
                            </EditItemTemplate>
                            <ItemStyle Width="70px" />
                        </asp:TemplateField>
                        <asp:BoundField DataField="new_LC" HeaderText="Cost" SortExpression="new_LC" DataFormatString="{0:c}" ItemStyle-Width="50px"/>
                        <asp:BoundField DataField="margin_current" HeaderText="Current Margin" 
                            SortExpression="margin_current"  ItemStyle-Width="50px" DataFormatString="{0:P1}"/>
                        <asp:BoundField DataField="margin_new" HeaderText="New Margin" 
                            SortExpression="margin_new"  ItemStyle-Width="50px" DataFormatString="{0:P1}"/>
                        <asp:BoundField DataField="tag_type" HeaderText="Tag Type" 
                            ItemStyle-Width="50px" >
                        </asp:BoundField>
                        <asp:BoundField DataField="effective_dt" HeaderText="Effective Date" 
                            DataFormatString="{0:MM/dd/yyyy}" ItemStyle-Width="50px" >
                        </asp:BoundField>
                    </Columns>
                </asp:GridView>
            </div>

In c#:

protected void ChangedUPCs2GridDataBound(object sender, EventArgs e)
    {
        ChangedUPCs2.HeaderRow.Attributes["style"] = "display:none";
        ChangedUPCs2.UseAccessibleHeader = true;
        ChangedUPCs2.HeaderRow.TableSection = TableRowSection.TableHeader;

    }
Circassia answered 11/1, 2012 at 16:45 Comment(0)
C
0

There is nothing built-in for ASP.NET that will allow for doing this, a part from buying tools which do support it (like Telerik controls). But it can be done, the key is to build every possible sort that the user could end up selecting. And tying them to their respective event. This is no easy feat with a table having as many columns as you have. Probably the best technique would be to build a stored procedure that could handle the individual requests, but I wouldn't describe it as simple either. Sorry.

Chez answered 12/1, 2012 at 18:49 Comment(1)
I like the stored procedure idea if you're into dynamic sql. That is how I would do it IF i were building it with foreknowledge. Then again telerik isnt THAT expensive...Winton
C
0

you can add some buttons to your page that sort with what ever you want

and with c# code you can sort items and fill gridview

i hope helped.

Cupro answered 13/7, 2014 at 20:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.