Loading user control dynamically from server side - asp.net

I have a user control which inherits a class. (and I did some coding on Oninit function of this class). I am loading that user control dynamically from server side using the following approach:
Mycontrol dc = (Mycontrol)Page.LoadControl("/Controls/Mycontrol.ascx");
MyPlaceHolder.Controls.Add(dc);
But the problem is that with this the Oninit function of the class inherited by the user control has not been executed. Can any one please tell me why this is happening and what is the solution for this.
Thanks,

According to the MSDN reference for page life cycle events, the OnInit of child controls are called before the OnInit of the page.
That means that you have to add your dynamic controls in the PreInit event to have them in place before the event chain starts. In fact, the documentation for PreInit states that:
Use this event for the following:
Check the IsPostBack property to determine whether this is the first
time the page is being processed. The IsCallback and
IsCrossPagePostBack properties have also been set at this time.
Create or re-create dynamic controls.
Set a master page dynamically.
Set the Theme property dynamically.
Read or set profile property
values.

Related

ASP.net PreInit() Vs Init()

From local forum i understood that PreInit can be used to handle the following
PreInit()
>Master pages can be called dynamically
>Themes can be set dynamically
>Programatically add controls to controls collection
and i read Init() is for
Init()
In this event, we can read the controls properties (set at design time). We cannot read control values changed by the user because that changed value will get loaded after LoadPostData() event fires.
Question
I am not getting the point "We cannot read control values changed by the user".Where do
users change the value of control?.Example would help me to understand the point.
PreInit: Raised after the start stage is complete and before the initialization stage begins.
Use this event for the following:
Check the IsPostBack property to determine whether this is the first time the page is being processed. The IsCallback and IsCrossPagePostBack properties have also been set at this time.
Create or re-create dynamic controls.
Set a master page dynamically.
Set the Theme property dynamically.
Read or set profile property values.
Init: Raised after all controls have been initialized and any skin settings have been applied. The Init event of individual controls occurs before the Init event of the page.
Lets say you have a textbox, a dropdownlist, some check boxes... the user enters data into them and you want to read their values by writing
var text = myTextBox.Text;
var selectedItem = ddl.SelectedItem;
this you cannot do before after the LoadPostData method has been called.
This page gives a pretty good summary of the different events and what they should be used for http://msdn.microsoft.com/en-us/library/ms178472.aspx. It says that PreInit should be used for ie. creating dynamic controls and Init for setting properties on them.
On the first post, you show several controls, say a textbox and a submit button.
The user types code into the textbox and click submit.
The user has changed the value of the control when he typed it in the textbox and it then got posted back to the page.
You will not be able to access the value typed in until LoadPostData has processed.
This is the pretty much the same with all other server side controls.
PreInit:
Initialize master page , user controls , dynamic controls
Init :
set the properties of controls
The value is changed through PostBack. The changes in the form data is determined by the current ViewState (which isn't loaded until later) vs the form data. Seeing as that isn't loaded until later, then you can't read any control values at that point.

What exactly does a server control e.g. a TextBox do, around the time it fires its Init event?

My understanding is a server control's constructor is called by the page's constructor. This happens before Page_PreInit event. A server control's Init event fires after Page_PreInit. It seems a server control does not do much during the Init stage? Then why bother giving much emphasis to Init stage?
The server control constructor is called in Page.ProcessRequest, which is after the Page's constructor has fired. You are correct that the initial control tree is completely created by the time Page_PreInit is called. Initializing a control in its constructor is too early for many controls, because Control.Page is null (it is set after the server control is created and the control is added to the control tree).
TextBox doesn't make much use of the earlier parts of the page lifecycle. Other controls, like GridView or the Repeater, do though. The key difference between Init and Load, is that Init occurs before viewstate is loaded, and Load occurs after. You're not going to understand the purpose of Init until you truly understand viewstate.
I'm not entirely sure this is what you're looking for but a TextBox control inherits from System.Web.UI.WebControls.WebControl which in turn inherits from System.Web.UI.Control which is the object that defines the Init event regardless of whether the TextBox control requires it or not.
Whether this event is used or not depends on the requirement of the control inheriting this object. If you were wanting to create a custom web control and you needed to do something at the initialisation stage then you can access this stage via the OnInit method.
Hope this helps.

ASP.NET Inherited UserControl, Events Sequence Question

I have a UserControl inheriting from another, and my question is simple. Does the control's page load fire first, or does the base class page load fire first?
"The Page calls the OnLoad event method on the Page, then recursively does the same for each child control, which does the same for each of its child controls until the page and all controls are loaded."
From this link: http://msdn.microsoft.com/en-us/library/ms178472.aspx
So to answer plainly, the Page_Load event is called before the load event in user controls
If you are talking about an actual inheritance, and not control composition, then all the standard Object Oriented rules apply.
Because these are not separate object, there is only one Load event on your control, and there can be only one Page_Load method, unless you explicitly hide it using the new modifier. So, in essence, there is no difference between the Child page load, and the Parent page load... they are one in the same.
The control's Page_Load should fire first, I believe. Other than the Page_Init event, all other initiation events occur up the control hierarchy.
Edit: I'm wrong up there. The page fires its load event then recursively calls it on child controls, which recursively call it on its child controls, and so on. My bad...

How do you access Control.ViewState with a dynamically added Control subclass?

We have created a control that needs to persist data via the ViewState property of the Control class. Our class subclasses control strictly to get access to the ViewState property (it's protected on the Page object). We are adding the control to Page.Controls in OnInit, and then attempt to set the ViewState property in OnPreLoad.
When we decode and examine the ViewState of the page, our values have not been written out, and are thus not available for later retrieval.
Does anyone know how we can get our control to participate in the ViewState process?
The issue is adding the control to the Page directly. Unfortunately this is too high up the controls hierarchy to participate in the Forms ViewState Handling. If you add the control onto the actual ASPNet Form's Controls collection somewhere then it will successfully participate in LoadViewStateRecursive and SaveViewStateRecursive.
Try creating your control in OnInit, then add it to the Page.Controls during OnLoad.
ViewState isn't loaded until after OnInit, but before OnLoad.
Here's a rough outline of the Page Life-Cycle(GregMac) posted this in a response to an earlier question of mine.
Initialize
LoadViewState
Load Postback Data
Call control Load events
Call Load event
Call control events
Control PreRender
PreRender
SaveViewState
Unload

ASP.Net: User controls added to placeholder dynamically cannot retrieve values

I am adding some user controls dynamically to a PlaceHolder server control. My user control consists of some labels and some textbox controls.
When I submit the form and try to view the contents of the textboxes (within each user control) on the server, they are empty.
When the postback completes, the textboxes have the data that I entered prior to postback. This tells me that the text in the boxes are being retained through ViewState. I just don't know why I can't find them when I'm debugging.
Can someone please tell me why I would not be seeing the data the user entered on the server?
Thanks for any help.
This is based on .NET v1 event sequence, but it should give you the idea:
Initialize (Init event)
Begin Tracking View State (checks if postback)
Load View State (if postback)
Load Postback Data (if postback)
Load (Load event)
Raise Changed Events (if postback)
Raise Postback Events (if postback)
PreRender (PreRender event)
Save View State
Render
Unload (Unload event)
Dispose
As you can see, the loading of ViewState data back to the controls happen before the Load event. So in order for your dynamically-added controls to "retain" those values, they have to be present for the ASP.NET page to reload the values in the first place. You would have to re-create those controls at the Init stage, before Load View State occurs.
I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If IsPostBack Then
CreateMyControls()
End If
End Sub
I believe you'll need to add the UserControl to the PlaceHolder during the Init phase of the page life cycle, in order to get the ViewState to be filled in by the Load phase to read those values. Is this the order in which you're loading those?
Ensure you are defining your dynamic controls at the class level and adding them to the ASP container:
Private dynControl As ASP.MyNamespace_MyControl_ascx
And when you instantiate the control, ensure you call LoadControl so the object is added properly:
dynControl = CType(LoadControl("~/MyNamespace/MyControl/MyControl.ascx"), ASP.MyNamespace_MyControl_ascx)
You have to create your controls in the Page_PreInit event handler. The ASP.NET server control model is tricky; you have to fully understand the page lifecycle to do it right.
As others have said, any form of control manipulation must be done before viewstate is created.
Here is a good link on the page lifecycle to help you out:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
We have experienced the same thing and have handled it by using ghost controls on page_load that have the exact same .ID and then the post back picks up the events and the data. As others said it's the dynamic adding of the control after the init stages that the state is built already and controls added after aren't stored.
Hope this helps a bit.
I also want to add that I've seen user controls work the way that you'd expect them to just by setting the Control.ID property at run time. If you do not set the ID, items may get built in a different order and work oddly.

Resources