Friday 15 May 2009

Remembering Page Index when returning to a List Page

This article is a continuation of the previous Retaining Pager Size in Dynamic Data GridViewPager now we want to retain the page index when moving between pages. For this we will use AJAX History.

Note: Also see this article back in February AJAX History in a Dynamic Data Website

I won’t go over the AJAX History in detail as Mike Ormond has done a great video on it on MSDN Screencasts here Managing Browser History with ASP.NET AJAX and the ASP.NET 3.5 Extensions Preview.

So let’s start.

Fist we will add a global private variable  to hold a reference to the ScriptManager.

private ScriptManager _scriptManager;

Next we need to initialise a few things

/// <summary>
/// Handles the Init event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">
/// The <see cref="System.EventArgs"/> instance 
/// containing the event data.
/// </param>
protected void Page_Init(object sender, EventArgs e)
{
    // get the containing GridView
    _gridView = this.GetParentOfType<GridView>();
    if (_gridView != null)
    {
        // add event to GridView to collect page index changed
        _gridView.PageIndexChanged += GridViewPageIndexChanged;

        // get the datasource on the gridview
        var GridDataSource = _gridView.FindDataSourceControl();
        
        // get the table
        _table = GridDataSource.GetTable();

        // Add OnNavigate handler to restore History points.
        _scriptManager = ScriptManager.GetCurrent(Page);
        if (_scriptManager != null)
            // add the navigate handler
            _scriptManager.Navigate += ScriptManagerOnNavigate;
    }
}

Listing 1 – Page_Init for the GridViewPager

In Listing 1 we get the GridView and ScriptManger, we then add a handler for the PageIndexChanged event on the GridView and add an event handler for the Navigate event of the ScriptManager.

/// <summary>
/// Grids the view page index changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">
/// The <see cref="System.EventArgs"/> 
/// instance containing the event data.
/// </param>
protected void GridViewPageIndexChanged(object sender, EventArgs e)
{
    // add history point
    if (_scriptManager != null)
        _scriptManager.AddHistoryPoint("PageIndex", _gridView.PageIndex.ToString());
}

/// <summary>
/// Scripts the manager on navigate.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">
/// The <see cref="System.Web.UI.HistoryEventArgs"/> 
/// instance containing the event data.
/// </param>
protected void ScriptManagerOnNavigate(object sender, HistoryEventArgs e)
{
    // restore history point
    if (!String.IsNullOrEmpty(e.State["PageIndex"]))
        _gridView.PageIndex = int.Parse(e.State["PageIndex"]);
}

Listing 2 – Handlers for the PageIndexChanged and Navigate events

Updated: Removed HistoryPointValue = e.State["PageIndex"]; not required. I think HistoryPointValue was originally a global private member variable.

In Listing 2 we are adding history points and restoring them again we also add a history point in Listing 3 if the page index TextBox is changed.

protected void TextBoxPage_TextChanged(object sender, EventArgs e)
{
    if (_gridView == null)
        return;

    int page;
    if (int.TryParse(TextBoxPage.Text.Trim(), out page))
    {
        if (page <= 0)
            page = 1;
        if (page > _gridView.PageCount)
            page = _gridView.PageCount;
        _gridView.PageIndex = page - 1;

        // add history point
        if (_scriptManager != null)
            _scriptManager.AddHistoryPoint("PageIndex", _gridView.PageIndex.ToString());
    }
    TextBoxPage.Text = (_gridView.PageIndex + 1).ToString();
}

Listing 3 – Changes to the TextBoxPage_TextChanged event handler

And that is pretty much it HappyWizard

4 comments:

trialot said...

small error in Listing 2, I believe...

Should there not be:

string HistoryPointValue

Stephen J. Naughton said...

Thanks the line should not have been there at all.

Steve :D

trialot said...

Noticed that too...I already changed it

By the way, two remarks/questions.

The degree of invisibility of (inline) updates is somewhat cumbersome. Is there a way to make those updates more visible?

Associated to the above: some topics are discussed by means of a set of ordered articles.
The logic between those articles is not always clear, mostly as a consequence of updates. In the worst case, one of the articles is updated and other articles (following or preceeding) are not.
Is there a solution?

Suggestion: is it not an idea to make lists of updates ?

Stephen J. Naughton said...

It's not easy with blogger to keep things tidy, I would really like to have my start page just show the titles of posts and the first few linw like ScottGu;s blog http://weblogs.asp.net/scottgu/ at some point I will find abetter blogging engine or write one then things can be a bit more ordered.
Bt thanks for the concern, if you have any question you can always chat using Digsby on the left and I can try to resolve the issue.

Steve :D