Labels

Friday, September 5, 2008

Dynamically Controls Loading - ViewState

Hi,

Here we’ll discuss, what is required to deal with dynamically control adding/loading.

The two best examples are –

- DataGrid Creation

- Adding Bound/Template columns in DataGrid

- Loading User Controls

Dynamic Controls Adding –

- In ASP.NET, dynamically loaded controls require a bit of attention because of their behavior across postbacks.

- In ASP.NET, each page request is treated independently from any other previous or successive requests. So a brand new instance of the page class is created to service each incoming request.

- This new page contains fresh instances of all server controls that are statically referenced in the ASPX source code.

- But what about the dynamically added controls? The page doesn't know about them unless the code in the page adds them again - Either by recreating of restoring by some persistence mechanism.

- In case of 'Dynamic Control Loading', the controls must be generated on every postback (not just when the page is first loaded).

- While regeneration, exactly the same order and with the same ID values must be maintained

- Unlike control values, dynamically generated controls are not maintained in the viewstate of the page

- However, values are maintained in the ViewState and will be reloaded after the controls have been created and added to the control tree.

Here comes the two questions, viz.

- In which Page Events, the controls should be recreated and added to the control tree?

- How the values are ‘Reloaded’ then?

Here is the answer, viz.

- There could be two events where ReCreation & Addition to the control tree can happen, viz. Page_Init or Page_Load.

- Page_Init -

- In this case, the values can be reloaded from the ViewState/PostData safely.

- Reason - ViewState/PostData is unpacked and processed between the Init and Load events – LoadViewState & LoadPostData Events.

- For e.g in below code snippet - If this information is stored in Session or Cache, then we could have safely access it from the Init event handler. But as this information is stored in the view state bag, then we have to use the Load event

- Page_Load -

- In this case, there could be a trouble as the ViewState/PostData is already unpacked and processed between the Init and Load events.

- How will you do it ?? Here is the Gotcha.

- Basically, posted data is processed in one of two passes—once before or once after the Page__Load event.

- Data for which no matching control is found in the first round is cached and processed again after the Load event.

- In the Load event, developers should check which controls were dynamically added the previous time and reload them in the page control tree.

- Nicely enough, the Add method of the Controls collection automatically updates the state of the control with any data found for that control in the view state

Facts – Choosing the Event when Adding Controls – Insider Solutions Book

- Instead of generating the controls during other ASP.NET page events, such as Init or Render, we had most success getting the process to work reliably, especially when wiring up event handlers, by using the Page_Load event.

- The controls must be generated on every postback (not just when the page is first loaded) and in exactly the same order and with the same ID values.

- Unlike control values, dynamically generated controls are not maintained in the viewstate of the page. However, values are maintained and will be reloaded after the controls have been created and added to the control tree.

Few Examples –

Dynamically Loading UserControl in Page_Load

public partial class _Default2 : System.Web.UI.Page

{

public string TrackedUserControl

{

get { return ViewState["TrackedUserControl"] as string; }

set { ViewState["TrackedUserControl"] = value; }

}

void Page_Load(object sender, EventArgs e)

{

if (!IsPostingFromMenu() && IsPostBack)

{

ReloadContent();

}

}

protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)

{

LoadContent(e.Item.Value);

}

private void LoadContent(string menuItemName)

{

string ucUrl = menuItemName + ".ascx";

UserControl uc = null;

uc = this.LoadControl(ucUrl) as UserControl;

Placeholder1.Controls.Add(uc);

TrackedUserControl = ucUrl;

}

void ReloadContent()

{

UserControl uc = null;

uc = this.LoadControl(TrackedUserControl) as UserControl;

Placeholder1.Controls.Add(uc);

}

}

Hope this helps.

Thanks & Regards,

Arun Manglick || Senior Tech Lead

No comments:

Post a Comment