Friday, September 16, 2005

ViewState

StateBag contains key-value pairs.

When you set a value for any key, it first checks to see if IsTrackingViewState is true or not.
[IsTrackingViewState is false by default. It is set to true when the TrackViewState() method is called]
If IsTrackingViewState returns true, the item that is being set is marked as dirty.

SaveViewState() method, when called, takes all dirty items and saves their values and returns that saved object of type "object array".

So, even though you add items to the StateBag, only those items that were set AFTER TrackViewState() has been called will be saved across postbacks.

In Page class, ViewState object if of type StateBag.
Right after the Init stage, the TrackViewState() method is called on all the Page's child controls and on the ViewState StateBag also.

In Custom controls, when ever a child control is added to the Custom Control's ChildControl collection, the Controls.Add method itself calles the TrackViewState() method on the newly added child control.
So, if you want to assign some values to the child control only once and let the control load these values from teh ViewState bag, every time the page is posted back, you MUST assign those values AFTER you have added the control to the Custom control's child collection.

Ex:
Controls.Add(btnNext); // --- (A)
if(!Page.IsPostBack)
{
btnNext.CommandName = "Some_Command_Name"; // Do this AFTER adding btnNext to the Child Controls collection (A), if you want that CommandName value to be loaded in the ViewState bag.
}

INamingContainer - Custom Controls

Your custom control MUST implement this Marker interface if it needs to handle any of its child control's events.
INamingContainer interface identifies your control as a container control that creates a new ID namespace within a Page object's control hierarchy.

INamingContainer is a marker interface that, when implemented by a control, creates unique IDs for its child controls. This naming scheme guards against potentially dangerous naming collisions. the ASP.NET runtime will throw an exception if a server control inside the page template has the same ID as a control on the calling page.

Ex: Suppose your custom control is given and "custDG" as its ID in the aspx page and that your custom control has a Button control as one of its children.
















 Custom control implements INamingContainer interfaceCustom control does not implement INamingContainer interface
You do not assign any ID to the Custom Control's Child controlinput type="button" name="custDG:_ctl0"

Programmatically, on the server side, you can access the button's ClientID as custDG__ctl0. But it doesn't make any sense on the client side as the Control doesn't output "ID" attribute of the button.
input type="button" name="_ctl0"

Does not fire the server side events of these Child Controls.
You do assign "MyBtn" as the ID to the Custom Control's Child controlinput type="button" name="custDG:MyBtn" ID="custDG_MyBtn"input type="button" name="MyBtn" id="MyBtn".

Does not fire the server side events of these Child Controls.


For a Child Control to save its state in ViewState and load it on postback, it has nothing to do with whether the Custom Control implemented the INamingContainer interface or not.