In ASP.Net, why can't I access a server control's properties from the ASPX page's constructor? - asp.net

In object-oriented languages, if class A contains class B as a member, you can access class B's properties from class A's constructor (after you instantiate class B first).
However in ASP.Net, my understanding is that a Page object contains server control objects as its members, but I do not understand why, if you try to access a server control's properties from the Page constructor, you get a NullReferenceException.

It sounds more like a Life Cycle problem. The controls contained on your page is not created at the same time as your Page object, but later in the cycle of your httprequest.
This page gives a clear picture of the cycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx.
You should instead override the Init-method to be sure your controls are initialized. Quote from the article
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.
Use this event to read or initialize control properties.

In the constructor, the ASPX has not run yet, so all of the server-side controls are null.
Move your code to Page_Load.

Related

ASP.NET User Control instance is null when referenced on Page_Load on page code behind

I have a user control that I have written and have added to an ASP.NET page, and functions just fine. However, I am trying to reference a property in the that custom control from code behind, on Page_Load, but cannot, because the variable, which is accessible, for the instance is null.
Is this normal for user controls and Page_Load? And if so, how can I make a reference to the control's instance in order to access its public properties? This is something I need to do before the page is rendered, in order to initialize some variables.
I had the same issue, and it turned out that I was registering my custom control incorrectly.
Correct Definition:
<%# Register Src="PeriodControl.ascx" TagName="PeriodControl" TagPrefix="ucs" %>
Incorrect Definition:
<%# Register TagPrefix="ucs" Namespace="MyWebsite" Assembly="MyWebsite" %>
The only difference was to reference the ascx file directly instead of the control in the assembly. Go figure!?
You can probably access your user control from the Page_PreRender event.
You can find more documentation about the page life cycle in asp.net here.

asp.net webforms - composite controls interacting with page controls

I am writing a composite control in c# asp.net as an experiment and would like to have all the instances of my composite control interact with one external control. Is this possible?
Things I have tried:
option 1: check from within the control whether an external control exists on the page, and add it if it doesn't
option 2: have the target control's id passed to the composite control at design time and then use this.Page.FindControl()
Obviously it was wishful thinking that it would be that simple :)
If I try do this from within the CreateChildControls Method, this.Page.FindControl(target control) always returns null. If I try to add the control to the page from within this method, it throws an exception:
"The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases."
is there another method / event where I can achieve this?
Why don't you expose a public property on your Composite Control of what output from them, then when rendering the Panel's contents, recurse through the page, find all instances of the composite control, grab the text, and add it to the panel?
You can create multiple instances on the same Web form by implementing the INamingContainer Interface. This basically helps prevent id clashes in the same namespace.
If you want to access another control set a property on it to expose the data you want made public.
Build Composite Controls

Server ccntrols in user control are null when user control serves as a base user control (asp.net)

I don't think I understand fully how ASP.NET does inheritance of controls.
I have a user control, ucBase, which has an asp.net label in the ascx file. Code behind references the label and it works fine during run time if the control is not a parent for another user parent.
If I have another user control, ucChild, inheriting from ucBase, the label in ucBase's code is always null. ucChild has no controls in its ascx file
The server controls (like the label) needs to be declared in the ascx file and not created programmatically.
What needs to be done for ucBase to see its own controls when it's a parent user control?
The issue:
Inheritance only inherits the code part of your user control. Markup is not something that can be inherited, since it is dynamically compiled at runtime.
The relationship between the markup and your code-behind is done through the .designer.cs partial class that comes with your user control. This designer file contains declarations for all the objects in your markup. This basically decorates the code-behind class with a bunch of fields that are null object references - these will be initialized with actual instances when the compiled markup code is run.
When you inherit from the .ascx file, you are inheriting all these null object placeholders. However, since the markup in your new control is not the same as the parent control, none of those objects are actually created when the new control's markup doesn't contain the corresponding markup, and when it is parsed and compiled, all the references stay null. Does this make sense?
The fix:
The best way to do this is to make your user controls self contained, i.e. favor code-based composition rather than markup based. In other words, instead of using markup, set up your user control using Page_Init and adding all the controls you need to the Controls collection in code behind.
Then when you inherit this class, all the same code will be executed, ensuring that your child usercontrol has the same UI controls in it.

When are controls initialized with their design time values?

a) Am I right in assuming that only after controls on Master page are merged into the control tree for the Page, can controls ( both those in Master page and in a content Page ) be initialized with their declarative values ( values set during design time )?
b) If my above assumption is correct, then these controls cannot be initialized with their design-time values during Page.PreInit, since during Page.PreInit event stage we’re still able to dynamically set a Master page?! So if that is the case, when are controls initialized with their declarative values? During Init event or…?
thanx
Pages are compiled into .Net classes, so the parsing of the markup actually happens outside of the page lifecycle. By the time a request reaches your Page, the page class has been compiled from the combination of the markup and codebehind.
This is easily verified by just putting a Page_PreInit handler and looking at the properties of a control on the page. You'll see that they are set.
The MasterPage/Page relationship is just a function of how the HTML will get rendered, and the naming containers that everything lives in.
When the actual Page compilation happens is partially a function of how you've set up your project, and partially a function of ASP.Net's monitoring of the files in the application.

When extending a asp.net web control, at which event should additional web controls be injected?

I'm trying to avoid a composite control or using and ASCX by extending an existing control. However, I'm having trouble with getting the controls added to the inherited control and keep their view-state/post-back integrity. Whenever I add the controls during pre-render, the controls show up, but the post-back throws a viewstate exception. I tried adding them both there and during LoadViewState (which of course was a long-shot silly). Init is not available from the control which I'm extending.
The exception is
Sys.WebForms.PageRequestManagerServerErrorException:
Failed to load viewsstate. The control
tree into which viewstate is being
loaded must match the control tree
that was used to save viewstate during
the previous request. For example,
when adding controls dynamically, the
controls added during a post-back must
match the type and position of the
controls added during the initial
request
Actually, microsoft says you should override the CreateChildControls method.
You can call the base class method before or after you add the controls, I'm not sure if there is a convention there.
protected override void CreateChildControls(){
Controls.Add(someControl);
base.CreateChildControls();
}
Hope that helps!
You should add them in OnInit or in CreateChildControls. Anyway, to avoid having troubles with ViewState, read this GREAT article. Possibly, sample "4. Initializing child controls programmatically" is your case.

Resources