Using a custom control in the base class of the page

I have a base page class that inherits from the page. We will call it SpiffyPage.

I also have a SpiffyControl user control.

Then I have an aspx page, ViewSpiffyStuff.aspx, which inherits from SpiffyPage.

When loading the page, the SpiffyPage class must inject SpiffyControl onto the aspx page.

The problem is that SpiffyControl is a user control, and in order to create an instance, which in code, one must access the ASP namespace, sort of like:

ASP.controls_spiffycontrol_aspx MyControl; 

But SpiffyPage is not an aspx page, it is just a base page, and therefore I cannot access the ASP namespace, therefore I cannot create an instance of SpiffyControl to enter it.

How can I achieve my goal?

Edit:

The important point is that I must have a reference to the actual type of control, so I can assign values ​​to specific user properties. Therefore, a function like LoadControl that returns a type of Control will not work in this case.

+7
source share
11 answers

Add a base layer to your SpiffyControl, for example:

 public class SpiffyBase : UserControl { public void DoIt() { Response.Write("DoIt"); } } 

and then you make your SpiffyControl an inheritance of this base word, for example:

 public partial class SpiffyControl : SpiffyBase 

then you should be able to do this from the Basepage class:

 public class BasePage : Page { protected override void OnLoad(EventArgs e) { var c = Page.LoadControl("SpiffyControl.ascx") as SpiffyBase; Page.Controls.Add(c); c.DoIt(); } } 
+10
source share

I would use SpiffyControl in a separate ASP.NET Server Control project and reference this project from a web application. Thus, the control will not be in the ASP namespace, but in the namespace of your choice and will behave like any other server control.

Update: A good side effect of placing user controls in a separate project is that they become more decoupled from the web application itself, which in turn makes them more reusable and, depending on their design, also more verifiable .

+4
source share

You guys are kidding me, I know that ASP.NET web forms were a painful experience, but no one had heard of the ClassName attribute, i.e.

 <%@ Control ClassName="SpiffyControl" Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Controls_SpiffyControl" %> 

So the original example:

 SpiffyControl spiffy = (SpiffyControl)LoadControl("~spiffy.ascx"); 
+2
source share

I'm not sure if this will help you, but there is a LoadControl method that can dynamically load a user control using the usercontrol username or usercontrol type. This method is in the System.Web.UI.TemplateControl class.

 Control userControl= LoadControl("usercontrol.ascx"); panelControl.Controls.Add(userControl); 
+1
source share

You can move your SpiffyControl to the library - this will give it a more accurate namespace and also allow you to use it in other projects. This is a bit complicated, but you already have UserControl installed, but it will not work in the library. UserControls uses the codebehind model - they consist of two files, one markup and one code. Libraries do not seem to support the codebehind model, so you cannot use UserControl. You need to convert this user control to a web control.

Create a new class library project. Open the project properties and set the AssemblyName and default namespace to SpiffyLibrary.

Now we need to convert your UserControl. First create a class in your new library. Call it SpiffyControl, like an existing user control, but inherit it from System.Web.UI.WebControls.CompositeControl.

Secondly, open the code of an existing user control and copy everything inside the class. Then go back to the new class and paste it inside. If you use any standard control events, you may need to rename these functions to override the corresponding events. For example,

 protected void Page_Load(object sender, EventArgs e) { ... } 

... must become ...

 protected override void OnLoad(EventArgs e) { ... base.OnLoad(e); } 

Third (this is the hard part) you need to reproduce all the markup you had in the SpiffyControl markup file. You can't just copy it - instead, you need to override the CreateChildControls () function, which is inherited from CompositeControl. Each tag that you had in the markup should be created as a variable and added to the Controls collection of the class. For example, if your existing markup file looks like this:

 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Controls_SpiffyControl" %> <div id="Div1" runat="server"> <asp:Label ID="TextOutput" runat="server" /> </div> 

... then your new CreateChildControls function should look like this:

 HtmlGenericControl Div1; Label TextLabel; protected override void CreateChildControls() { Div1 = new HtmlGenericControl("div"); this.Controls.Add(Div1); TextLabel = new Label(); Div1.Controls.Add(TextLabel); base.CreateChildControls(); } 

Note that controls are declared as class fields; Thus, they are visible to all class methods.

Once you convert your markup, compile the library project and add it to the links for your website project. Then open the web.config file and find the system.web / pages / controls section. This section should already have a tag:

 <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 

This tag allows you to use controls from major ASP libraries. Therefore, we are going to add it in the same way as for our library:

 <add tagPrefix="spiffy" namespace="SpiffyLibrary" assembly="SpiffyLibrary" /> 

Now, anywhere in your site, you can add markup as follows:

 <spiffy:SpiffyControl ID="SpiffyInstance" runat="server" /> 

... and this will load your web control from your user library.

+1
source share

Despite the fact that your database is not an ASPX page, you can inherit it from the same framework class as it is:

 public abstract class MyBasePage : System.Web.UI.Page { } 
0
source share

Assuming SpiffyControl and SpiffyPage are in the same namespace:

  Control spiffyControl = LoadControl("SpiffyControl.ascx"); (control as SpiffyControl).SpiffyControlProp1 = true; (control as SpiffyControl).SpiffyControlProp2 = "Hello, World!"; 
0
source share

You can also simply define the namespace of your SpiffyControl manually. To do this, you need to change the code and markup.

In code, move your class to a namespace block. Therefore, if your class was

 public partial class Controls_SpiffyControl : System.Web.UI.UserControl { ... } 

... then change it to ...

 namespace Spiffy { public partial class Controls_SpiffyControl : System.Web.UI.UserControl { ... } } 

Then, in the markup, adjust the @Control header. Therefore, if your @Control header was

 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Controls_SpiffyControl" %> 

... then change it to ...

 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Spiffy.SpiffyControl" %> 
0
source share

Assuming that you will be working in an environment that supports reflection, you can use these methods.

 private void SetValue(Control control, string propertyName, object value) { Type type = control.GetType(); PropertyInfo property = type.GetProperty(propertyName); property.SetValue(control, value, null); } private object GetValue(Control control, string propertyName) { Type type = control.GetType(); PropertyInfo property = type.GetProperty(propertyName); return property.GetValue(control, null); } 

And name it as follows:

  Control control = this.LoadControl("~/SpiffyControl.ascx"); string propertyName = "Custom1"; object value = "Value"; SetValue(control, propertyName, value); 

If it is called a lot, you may need to cache type information.

You might also consider creating an ISpiffyControl interface in the assembly that hosts SpiffyPage, and then do your user control.

0
source share

This has been affected, but the interface should work. Make ISpiffyControl with any members / methods, implement it in SpiffyControl.ascx.vb and do it in SpiffyPage:

 Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) MyBase.OnLoad(e) Dim page As New Page Dim path As String = request.ApplicationPath Dim control as UI.Control = page.LoadControl(String.Format _ ("{0}/pathToUserControl/{1}.ascx", path, controlName)) Dim sc As ISpiffyControl = CType(control, ISpiffyControl) sc.DoSomethingSpecial() Me.Controls.Add(sc) End Sub 
0
source share

If I read this correctly, the source poster had a problem where it could not access the type of the base class from which the parent page was created in its UserControl, and not vice versa. It so happened that I had the same problem.

In my case, all the pages of my project are inherited from the same base, so I don’t worry that my user control has knowledge of the base class of the page. Apologies to the architects.

However, I solved the problem with a combination of 1) using a base class for my user control and 2) using a common namespace. This allowed me to see the visibility that I needed, because for some reason the base class of the user control still could not see the base class type of the base page class.

In any case, I just decided to share my results if they help someone else in the future.

NTN.

0
source share

All Articles