NewPageIndex Doesn't Get Updated in PageIndexChanging Event

G

Guest

We have a base class that is responsible for creating the navigation and look
and feel of our applications. So all our web pages inherit from this base
page so they don't have to worry about the look and feel and navigation, only
the main content. Everything has woked just fine until we converted to 2.0.
Now we have a problem with the new GridView and the paging. With the
DataGrid in 1.1, the paging worked just fine. Now with paging turned on and
the mode set to "NextPrevious" the NewPageIndex doesn't get updated in the
PageIndexChanging event. However if I change the web page to not inherit
from my base class but just from the System.web.ui.page then the paging works
correctly. This is a code snipit of our base class and how it loads the
controls from the derived page. I am really stumped on this one so if anyone
has any ideas it would be greatly appreciated.

ASPX Page:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
<asp:GridView ID="GridView1" runat="server" AllowPaging="true"
OnPageIndexChanging="GridView1_PageIndexChanging">
<PagerSettings Mode="NextPrevious"></PagerSettings>
</asp:GridView>


Code Behind (scaled down and only showing the basics):

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;

public partial class _Default : MyBasePage
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
GridView1.DataSource = GetDataSource();
GridView1.DataBind();
}
}

protected void GridView1_PageIndexChanging(object sender,
GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridView1.DataSource = GetDataSource();
GridView1.DataBind();
}

private DataSet GetDataSource()
{
OleDbConnection cn = new
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; Data
Source=C:\\Program Files\\Microsoft Visual Studio\\VB98\\nwind.mdb");
OleDbDataAdapter da = new OleDbDataAdapter("Select CompanyName,
ContactName, Address from Customers", cn);
DataSet customers = new DataSet();
da.Fill(customers, "Customers");
return customers;
}
}

public class MyBasePage : System.Web.UI.Page
{
HtmlForm objForm;

public MyBasePage()
{
objForm = new HtmlForm();
}

protected override void OnInit(System.EventArgs e)
{
BuildPage();
base.OnInit(e);
}

private void BuildPage()
{
for (int i = 0; i < this.Controls.Count; i++)
{
System.Web.UI.Control objCtrl = this.Controls[0];
objForm.Controls.Add(objCtrl);
this.Controls.Remove(objCtrl);
}
this.Controls.Add(objForm);
}
}
 
W

Walter Wang [MSFT]

Hi,

Thank you for your post.

First, this problem can be fixed by using following BuildPage() function:

private void BuildPage()
{
ArrayList al = new ArrayList();
foreach(Control c in Controls)
{
al.Add(c);
}
Controls.Add(objForm);

foreach(Control c in al)
{
objForm.Controls.Add(c);
}
}

Following are detailed causes:

1) The root cause of this problem is GridView's PageIndex is stored using
ASP.NET 2.0's new feature called "ControlState". See following MSDN for
more info:
http://msdn2.microsoft.com/en-us/library/system.web.ui.pagestatepersister.co
ntrolstate.aspx

A server control that use control state must call the
RegisterRequiresControlState method on each request because registration
for control state is not carried over from request to request during a
postback event. It is recommended that registration occur in the Init event.

GridView calls this method in its OnInit:

protected internal override void OnInit(EventArgs e)
{
base.OnInit(e);
if (this.Page != null)
{
if ((this.DataKeyNames.Length > 0) &&
!this.AutoGenerateColumns)
{
this.Page.RegisterRequiresViewStateEncryption();
}
this.Page.RegisterRequiresControlState(this);
}
}

Please note that it checks for "this.Page != null" first.

2) When adding a control to a ControlCollection, it will automatically
first remove it from its old parent.Controls (if its parent is not null),
and removing a control will Unload it first!

In previous code, when we first add the GridView to objForm.Controls,
because objForm is not added to Page.Controls yet, the "this.Page != null"
will be false for the GridView, thus not calling the
RegisterRequiresControlState.

So, what we are doing now is first adding the objForm to Page.Controls,
then add the remaining controls to objForm, this will ensure GridView's
ControlState is persisted.

As a side note, in ASP.NET 2.0, we have a new feature called MasterPage
which is exactly for the purpose of keeping a consistent look and feel for
the entire website.

Hope this helps. Please feel free to post here if anything is unclear.

Regards,
Walter Wang
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Walter, thanks for the reply. That fixed it. However, this brings up
another question. We currently use this base page for our 1.1 apps. We have
some groups in our company that are trying to use our base page compiled with
1.1 in their 2.0 web apps. This is the first issue we have ran into with
trying to use our 1.1 base code in a 2.0 app. If I go change our base page
to load the form into the page object before I load any controls into the
form collection, will this cause any problems with any of the 1.1 controls?

Also, in response to your side note, I wanted to use the Master pages but
unfortunately our base page is in a class library in a seperate assembly
rather than in the web application itself so there was no way to use the
master pages. At least this is what Microsoft told us. We distribute this
assembly throughout our company to let other development teams use in order
to have the corporate look and feel.
 
W

Walter Wang [MSFT]

Hi,

Thank you for your update and I'm glad that the suggestion worked.

Based on my research, adding an HtmlForm instance first is the preferred
way to mimic a normal ASP.NET page, since Control.Page property will use
parent to find the Page reference. If you add controls to HtmlForm first,
their Page reference are null and you don't know if they will check this
reference in OnInit or not. In a word, this "advanced" Page inheritance
technique is not officially supported so we have to test to see if it
really works.

As for the MasterPage issue, unfortunately it does need the *.master source
to be distributed.

Please feel free to post here if there's anything I can help.

Regards,
Walter Wang
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top