user2121236
user2121236

Reputation: 53

Sorting a ASP.NET 4.0 (c#) ListView

I have a ListView -- bound from a datatable -- containing several pages of chronological items.

I would like to be able to sort them in ascending and descending order.

In my <layouttemplate> I have the following:

<asp:linkbutton runat="server" id="SortbyYear" commandname="Sort" commandargument="Year">Year</asp:linkbutton>

When I click on that, I get an error from the pageRequestManager that onsorting is not handled.

So I added the following to my <asp:listview ... >:

onsorting="HistoryList_Sorting"

What do I actually put in that method in the code behind to get sorting to work? I am just try to toggle the column "Year" back and forth between ascending and descending.

protected void HistoryList_Sorting(object sender, ListviewSortEventArgs e)
{
    // WHAT GOES HERE???
}

UPDATE:

The following is what I have in my ASPX page:

<asp:listview id="HistoryList" runat="server" convertemptystringtonull="False" onlayoutcreated="HistoryList_LayoutCreated" ondatabound="HistoryList_DataBound" onsorting="HistoryList_Sorting" >
    <layouttemplate>
        <table>
            <tr>
                <th><asp:linkbutton runat="server" id="SortByYear" commandname="Sort" commandargument="Year"><asp:literal runat="server" id="Year" /></asp:linkbutton></th>
                <th><asp:literal runat="server" id="Event" /></th>
            </tr>
            <tr id="ItemPlaceholder" runat="server"></tr>  
        </table>
    </layouttemplate>
    <itemtemplate>
        <tr class="row">
            <td class="history-year-column"><%# Eval("Year") %></td>
            <td><%# Eval("Description") %></td>
        </tr>
    </itemtemplate>
    <alternatingitemtemplate>
        <tr class="row-alternate">
            <td class="history-year-column"><%# Eval("Year") %></td>
            <td><%# Eval("Description") %></td>
        </tr>
    </alternatingitemtemplate>
</asp:listview>

The following is what I have in my CS page:

#region " Declare: Shared Classes "

    private Localization localizeSite = new Localization();
    private DataXML xmlData = new DataXML();
    public DataTable HistoryDataTable { get; set; }

#endregion



#region " Page: PreInit "

    private void Page_PreInit(object sender, System.EventArgs e)
    {
        Page.MasterPageFile = localizeSite.LoadMasterPage(Page.Master.AppRelativeVirtualPath);
    }

#endregion



#region " Page: Load "

    protected void Page_Load(object sender, System.EventArgs e)
    {
        Edition edition = new Edition();
        ContentTracking.Text = edition.GetEdition(Page.AppRelativeVirtualPath);

        //// LOCALIZE THE WEB SITE CONTENT
        Heading.Text = localizeSite.LocalizeText(Page, "Heading.Text");
        Body.Text = localizeSite.LocalizeText(Page, "Body.Text");
        AdNetworkTracking.Text = localizeSite.LocalizeText(Page, "AdNetworkTracking.Text"); 
    }

#endregion




#region " Handle: OnLayoutCreated "

    protected void HistoryList_LayoutCreated(object sender, System.EventArgs e)
    {
        ((Literal)HistoryList.FindControl("Year")).Text = localizeSite.LocalizeText(Page, "Year.Text");
        ((Literal)HistoryList.FindControl("Event")).Text = localizeSite.LocalizeText(Page, "Event.Text");
    }

#endregion





#region " Handle: Sorting "

    public String SortExpression
    {
        get
        {
            return (string)ViewState["SortExpression"];
        }
        set
        {
            ViewState["SortExpression"] = value;
        }
    }

    protected void HistoryList_Sorting(object sender, ListViewSortEventArgs e)
    {
        String sortExpression = e.SortExpression + " " + e.SortDirection.ToString();
        this.SortExpression = sortExpression.Replace("Ascending", "ASC").Replace("Descending", "DESC");
    }

#endregion





#region " Handle: Paging "

    protected void HistoryList_DataBound(object sender, EventArgs e)
    {
        HistoryPager.Visible = (HistoryPager.PageSize < HistoryPager.TotalRowCount);
    }


    protected void HistoryPager_PreRender(object sender, EventArgs e)
    {

        if (HistoryDataTable == null)
        {
            HistoryDataTable = xmlData.GetDataTable(Server.MapPath("~/App_Data/history.xml"), "Event");
        }

        if (!String.IsNullOrEmpty(SortExpression))
        {
            HistoryDataTable.DefaultView.Sort = SortExpression;
        }

        HistoryList.DataSource = HistoryDataTable;
        HistoryList.DataBind();
    }

#endregion

Sorting is not working yet.

Upvotes: 0

Views: 6186

Answers (4)

Blake
Blake

Reputation: 11

If your list view is bound to a database could you just sort in the database select statement using an "order by" clause? This would return the data in sorted order and you wouldn't need to sort them in the list view itself.

I know this doesn't answer the sorting question, but thought I'd throw it out in case you hadn't considered it.

Upvotes: 1

Manish Mishra
Manish Mishra

Reputation: 12375

When you want to sort a ListView with a datapager, and you want to retain the sorting, upon page change, then you need to remember couple of things.

  1. You have to somehow determine, last Sort Direction i.e. when you sort a column, then you must be able to know, whether you clicked for the first time or the 2nd i.e. you wanted to Ascend or Descend

  2. you need to maintain the sortExpression, during page changes(post back). that implies, you need to presist the sorting in your datasource.

see the example below:

Create a ListView, and in its LayoutTemplate, in your headers for the ListView, place LinkButton with CommandName="Sort" and CommandArgument="ColumnName" i.e

<LayoutTemplate>
  <table>
    <tr>
       <td>
         <asp:LinkButton ID="btnNameSort" runat="server" 
            CommandName="sort" CommandArgument="Name" 
            Text="Name">
         </asp:LinkButton>
       </td>
        ..
        ..
</LayoutTemplate>

and then on codebehind do this:

public string SortExpression
{
     get
     {
        return (string)ViewState["SortExpression"];
     }
     set
     {
        ViewState["SortExpression"] = value;
     }
}
public DataTable lvwDataSource { get; set; }

and your listview sorting event as :

protected void lvwData_Sorting(object sender, ListViewSortEventArgs e)
{
   string sortExp = e.SortExpression + " " + e.SortDirection.ToString();
   this.SortExpression = sortExp.Replace("Ascending", "ASC")
                                .Replace("Descending", "DESC");
}

bind your listView in your DataPager's PreRender event:

protected void DataPager1_PreRender(object sender, EventArgs e)
{
   if (lvwDataSource == null)
        lvwDataSource = StaticData.GetData();

   if (!string.IsNullOrEmpty(SortExpression))
        lvwDataSource.DefaultView.Sort = SortExpression;

   lvwData.DataSource = lvwDataSource;
   lvwData.DataBind();
}

so, you need to define your datasource in a global scope, to persist sorting upon paging.

Upvotes: 0

Debasish
Debasish

Reputation: 68

if(e.commandName==Sort)
{
  //Code you want to implement on the button click event
}

Upvotes: 0

antinescience
antinescience

Reputation: 2359

I haven't done this myself, but it looks like you'd be doing something like this: asp.net ListView Sorting using DataBind. Hope it helps!

Upvotes: 0

Related Questions