ASP.NET 2.0 - Parent Page Class not accessible from custom control - asp.net

1) I've page class
public partial class MyDelivery : System.Web.UI.Page
2) ASCX is in different subfolder
public partial class MyControls_Hello_Bye : System.Web.UI.UserControl
I am unable to access #1 parent page class from control

This problem annoyed me for quite a while. I don't think my solution is perfect, but it sure helps my junior developers in coding. We have a base user control that all user controls inherit and we (like you) we have a base page class that all pages must inherit (team rule). In the user control is a property called ParentForm which is strongly typed to the specific page type that will contain it (the page baseclass if that is variable or unknown at the time).
During the load event of the page, we manually set the Parentform Property of all user controls (we do this in our master page for all master page level controls as well).
protected Page_Load(object sender, System.EventArgs e)
{
this.myControl.ParentForm = this;
this.myControl2.ParentForm = this;
}
This provides immediate access from any user control back to the page and any of its exposed methods. It also provides a standardized (within our team) method of allowing controls to communicate between themselves through an interface in the ParentForm.
Our standard is to perform this assignment manually. For me this was a personnel consideration to make sure developers are aware of the controls they are adding (not setting the ParentForm will cause null reference exceptions if you attempt to access it obviously). If you wanted to perform this setting automagically, you could use the base class's Page_InitComplete event to cycle through any user controls and set the ParentForm to "this" that way.

Being in a different directory would get visual studio to give them different namespaces by default, causing the parent page class not to visible to the control.
Make sure the namespace declarations of both classes are the same, or import the parent page class namespace to the contorl with the using statement.

Related

Are ASP.net Content Web Forms able to access variables declared in the Code Behind section of it's Master Page?

I have a Master Page which controls the styling of my site. In the Code Behind, there are a few class instances instantiated as well as variables. These classes validate user access and then create user objects
I have a few Web Content Forms which carries out instructions based on the user objects. So far it seems that on each Web Content Form I have to create new instances of the classes found on the Master Page. This is doubling my work for every Web Content Form.
Is there anyway I can inhereit Classes and objects instantiated in the Master Page Code Behind?
Expose the objects (and even controls) as public properties (get only for controls) on the Master page. Then, in each aspx page you want access to these objects, add the following declaration at the top:
<%# MasterType VirtualPath="~/MyMasterPage.master" %>
As #Kristof points out, simply access your properties like Master.PropertyName
Also, you can determine if it makes sense to store the objects in the users Session (don't forget that they must be serializable if you use DB for session state). I do this often and control access to them via properties in a base Page class that all my pages inherit from. Actually, I have a base master, page, and usercontrol so I have access to the same properties (for me it's CurrentUser) everywhere.
I believe you can if you make the properties public.
Then in your child-page you can make the call something like this:
SiteMaster master = (SiteMaster)this.Master;
master.MyProperty = 0;
Where SiteMaster is the class for your master page. (SiteMaster is the default for the app templates)
Though my mind can deceive me, I haven't done it for a while...

Accessing user controls’s constituent controls from a hosting web page

I’ve read that user control’s constituent controls can be accessed only by user control and thus web page that hosts this user control cannot receive the events, call methods or set properties of these contained controls.
But I’m not sure the above claim is true, since I was able to access ( from hosting web page ) ClickButton.Click event ( assume WebUserControl1 contains ClickButton control ):
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Button ClickButton = (Button)WebUserControl1.Controls[0];
ClickButton.Click += someClickHandler;
}
thanx
The entire page is a tree of controls. You can "browse" through this tree regardless of the parent of that control. For example from inside a user control you could go down to the parent, which could be another control, then further down to the page, then to the master page, and so on.
So yes, you are correct, it's not hidden to the point you can't access it, but it's not published either. In a similar way using reflection you could call private methods that you couldn't otherwise. Using certain tools you could access and change code that's already compiled; so nothing is really out of reach.
These boundaries are set and used to minimize complexity, not as an absolute wall that cannot be crossed.
You can expose the user control's properties (i.e. settings), controls, and events publicly which means you don't have to find the control within the usercontrol.

Using SavePageStateToPersistenceMedium() for Master Page ASP.NET

Please refer to the topic http://www.codeproject.com/KB/viewstate/SaveViewState.aspx. The topic demonstrates how you can save ViewState to a file system over server so as to make ViewState very small on roundtrips. The author had created a class BasePage by inheriting System.Web.UI.Page and all the pages are derived from this class.
The site I am developing uses a masterpage and all the pages are derived from this masterpage. When I try to override SavePageStateToPersistenceMedium(), a compilation error is generated indicating that there is no such method to override within System.Web.UI.MasterPage.
How could I solve this problem?
I have found the solution. Actually the aspx page is derived from System.Web.UI.Page while the masterpage is derived from Control class. There the method SavePageStateToPersistenceMedium() is available within aspx page only not in master page. You have to override this method within each aspx page or create your own base class derived from Page class and then override the method.
Using a PageStatePersister override would be an easier way to change the ViewState persistance mechanism on all pages without requiring a base class.
Milan Negovan has written a good blog post on the different options using the PageStatePersister, with some additional links.

LoadControl vs Construct ASP.Net Control

I have a question why we can only add dynamic control using LoadControl.
For example:
public partial class wucReportParam : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
wucDate() ctrl = new wucDate();
pnl.Controls.Add(ctrl);
}
}
When in the page_load method of wucDate, the child control of wucDate is null but when i use the following method:
public partial class wucReportParam : System.Web.UI.UserControl
{
public Report Report;
protected void Page_Load(object sender, EventArgs e)
{
ctrl = (wucDate)LoadControl(#"Reports\wucDate.ascx");
pnl.Controls.Add(ctrl);
}
}
In the page_load method of wucDate, the child control of wucDate is not null.
Is anyone could explain to me why asp .net don't create any child control of wucDate when i using contructor ??? Thank you
When dynamically loading a user control, it is important to ensure that the standard ASP.NET page event pipeline is initiated and progresses normally. When you use the new operator to create an instance of a user control, that user control is not properly added to ASP.NET's event system. If the events (Init, Load, PreRender, etc.) to not fire, then your control will never function properly. That is why it is necessary to use LoadControl, as that will make sure that the instance of your user control is created properly and attached to ASP.NET.
Apparently, using LoadControl with typeof (or GetType) has the same problem as using 'new' where the child controls are not initialized. Using LoadControl with a string to the ASCX file works.
Does not initialize child controls.
LoadControl(typeof(MyReport), null);
Works!
LoadControl("Report.ascx");
The initialization of the controls inside a User Control is driven by the ASCX file. Using only "new SomeControl" will not cause this initialization to run, and even if it did, all the design (markup) in the ascx file would be lost.
Remember that the class "wucDate" is only the base class which the full user control inherits from. It's not the same class as you'll get when using LoadControl("wucDate.ascx").
And to be honest, LoadControl has not much, if anything, to do with the page life cycle. That part is handled when you add the control to the container's Controls collection.
As I recall, it pertains to how ASP.NET constructs page components at run time. In ASP.NET although your pages have a class which is defined in your code-behind file, their types don't truly exist until run time. Like a page, although you have a control defined the wucDate type isn't created until it is included at run time. For this reason, the control must be loaded with LoadControl in order to both initialize the type and properly run in through the page life cycle.
This is to the best of my memory so if I'm incorrect here please let me know.

Access data on Page from Web Control

I created a web control, and it needs some data from its parent page.
How can it access that data?
Update: Thank you for the quick solutions, however they don't work for me. Visual Studio doesn't recognize the name of the page as a class. I took the name from where the class is defind:
public partial class Apps_Site_Templates_CollegesMain : cUICommonFeatures
(cUICommonFeatures inherits from System.Web.UI.Page)
But in the control, when I define
protected System.Web.UI.Page parentPage;
parentPage = (Apps_Site_Templates_CollegesMain)Page;
I get a compliation error:
The type or namespace name 'Apps_Site_Templates_CollegesMain' could not be found (are you missing a using directive or an assembly reference?)
I feel like I'm missing something really basic here, and I'll probably be very embarrassed when I get an answer, but I do need help....
If the parent page class is named lets say ParentPage, you can do this within the control:
ParentPage page = (ParentPage)this.Page;
Then you can access the properties and methods on ParentPage. If you have more pages using the same control, you should use an interface on the parent page to access the properties on the page.
IParentPage page = (IParentPage)this.Page;
Does that answer your question?
Controls should be written to be independant of what page they're on. If the control needs a piece of data, then it should expose a public property which is of the type of the data that it needs. The page it is on wo uld then set that property to the data that the control needs. This permits the control to be used on another page, or even made part of a UserControl and that UserControl then used on the parent page.
There are many ways to do that. I think the best one is adding a property for the data control needs and in your page set this property.
Also you can access to your page from your control like that :
string dataYouWant = ((YourParentPageName)Page).GetData();
Or you can add the data to viewstate, and read it from the child controls.
But as I said, I would choose the first one.
All Controls (server controls, usercontrols and custom controls) expose a property Page which allows you to access the containing Page instance from the code of the control.
Therefore, you could simply do:
// In Usercontrol code:
MyParentPage parentPage = this.Page as MyParentPage;
if (parentPage != null)
{
// Access the properties of the Parent page.
string t = parentPage.Title;
}
The article "Mastering Page-UserControl Communication" offers a good beginners introduction to control-Page interactions.

Resources