I have a very simple setup, single mycontrol.ascx with assoicated mycontrol.ascx.designer.vb and mycontrol.ascx.vb file.
mycontrol.ascx embeds a single reference to a custom control: "MyMenu":
<mM:myMenu id="myMenu1" runat="server" />
This has created a protected reference in the mycontrol.ascx.designer.vb file:
Protected WithEvents myMenu1 As Global.CustomControls.MyMenu
Now, when I breakpoint the Page_Load() event of mycontrol.ascx, and inspect the members returned from the type via:
Me.GetType().GetMembers()
I cannot any reference to myMenu1. If I look at the control with intellisence, the property is accessible:
Me.myMenu1
Can anyone explain exactly what I'm missing and what I need to do to access designer created properties at runtime through reflection?
Cheers
Yum.
Your .acsx file creates a separate class (generated by the compiler) that inherits the codebehind class.
GetMembers only returns the members defined directly on the class, not any members inherited from its base class.
You need to get the members defined on the base class, like this:
Me.GetType().BaseType.GetMembers()
what I need to do to access designer created properties at runtime through reflection?
I don't know your menu control but you don't need to grasp the members of the user control, you need to get to the members of the menu control.
myMenu1.GetType().GetMembers()
Besides why use reflection? Doesn't your custom control expose properties with which you can set your settings like
myMenu1.SelectedMenuItem = 3
Related
I'm trying to create an ascx control that can wrap content like a panel. I'm looking to do something like -
<%# Register TagPrefix="FOO" TagName="Section" Src="CollapsibleSection.ascx" %>
<Foo:Section runat="server">
[ Section of asp.net webforms page ]
</Foo:Section>
It has been a while since I've done web forms and cannot remember if this is possible to do? While I could write a fully custom control, there are many advantages in my app if this is possible.
You need to decorate your user control with TemplateContainerAttribute and inherit from INamingContainer.
This is referred to as a templated control.
Here's a simple tutorial explaining how this is done in both C# and VB.Net: How to: Create Templated ASP.NET User Controls
Quoted from MSDN (link above):
In the .ascx file, add an ASP.NET PlaceHolder control where you want the template to appear.
In the user control's code, implement a property of type ITemplate.
Define a server control class that implements the INamingContainer interface as a container in which to create an instance of the
template. This is called the template's naming container.
Apply the TemplateContainerAttribute to the property that implements ITemplate and pass the type of the template's naming
container as the argument to the attribute's constructor.
In the control's Init method, repeat the following steps one or more times:
Create an instance of the naming container class.
Create an instance of the template in the naming container.
Add the naming container instance to the Controls property of the PlaceHolder server control.
i want to create a user control that will display an image (the location of the image is store in my db) the control will have the ability to change the image or delete it.
i want to build another control that will hold some of that control.
what are the properties that i need to set or get from the first control to the second and then to the page that will hold them?
well, it seems that we are talking about inheritance,
in my first thinking to solve this quickly you have to create a class (maybe on app_code dir) that inherits from usercontrol. Here you gonna implements tha base methods that will be used for each derived classes.
when you have this "Base class" implemented your control will not inherits fom the default usercontrol, but will from your base class.
by this way you can create a kind of base class that provides adicional properies or methods for your purposes (thats a kind of extension if you dont understand much of oop)
i have a usercontrol named filebox (which wraps a fileupload and some related stuff)
in a certain .net class i have need to use this type as a ctype
but i cant seem to call ctype(aobject,filebox)
or either ctype(aobject,Controls_filebox) (which is the correct name)
how can i convert an object to this type?
thanks a million!
You need to add the class' namespace.
It's probably in the ASP namespace; you can check in the Object Browser.
You can change the namespace by adding Class="My.Namespace.Filebox" in the <%# Control directive.
While developing and ASP.NET application in C# or VB using Visual Studio 2005/2008/2010 (Not a problem in 2003), if I create a new method automatically by double-clicking on a control in the designer or picking the new method in the code editor dropdowns (VB only), the access modifier is always protected instead of private. This is annoying because my developers have to manually change the method to private every time.
Is there are way to tell visual studio to generate all new method headers as private instead of protected?
Please do not debate the reasons for wanting my methods to be private.
This can't work for the case where you double-click a control in the designer.
Double clicking a control in the designer not only creates in code-behind the code for the handler for the default event, it also changes the markup to refer to it. For instance, having added a Button to a web page, then double-clicking on it, I get:
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Yes" />
If I change the visibility of Button1_Click to "private", then I get a yellow screen of death:
Compiler Error Message: CS1061: 'ASP.default_aspx' does not contain a definition for 'Button1_Click' and no extension method 'Button1_Click' accepting a first argument of type 'ASP.default_aspx' could be found (are you missing a using directive or an assembly reference?)
The ASP.NET page is parsed and built to generate a class that derives from your codebehind class. That class needs to be able to reference things like your event handler.
Apparently, when used with VB.NET, this problem does not exist. The difference is that in VB.NET, the designer does not change the markup at all, so the class generated from the markup does not need to refer to the created event handler. It can safely be made Private.
However, since the designer, when used with C# does modify the markup such that the generated class does need to refer to the new event handler. In this case, the event handler cannot be made private.
From my understanding, this is a designer issue. Once the code of the page "matures" or before I check-in, I do a search-and-replace of "protected" for "private" then fix any resulting compilation errors.
It is your job, so why would it be "annoying"? :O)
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.