I want a Master UserControl (a Master page, but for UserControls)
Asked Answered
E

5

5

ASP.NET master pages - essential things.

However, I have a lot of very similar UserControls in my projects - it might be a standard layout for an AJAX ModalPopup, or something more involved.

I wish I could get rid of some of my duplicated code (both in ascx files and code-behind) with some Master UserControls.

Does anyone have any suggestions of a way to achieve this?

Ellipticity answered 2/12, 2008 at 14:57 Comment(0)
C
2

The closest thing I can suggest for what you are looking for is a templated custom control. Unfortunately, sharing controls across projects is a lot easier if those things are custom controls, without an ascx file.

Chaparral answered 3/12, 2008 at 5:9 Comment(0)
Q
4

this is an old question but i have a robust solution for anyone who stumbles upon this.

in app_code, create a file and paste this code:

namespace MasterControls
{
    // code written by alexander taylor on 2011-08-22. http://www.alexsapps.com

    public abstract class ChildUserControl : UserControl
    {
        Control master;

        public abstract string MasterControlVirtualPath { get; }

        protected override void OnInit(EventArgs e)
        {
            master = LoadControl(MasterControlVirtualPath);
            Controls.Add(master);

            base.OnInit(e);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            master.RenderControl(writer);
        }
    }
    public class ControlContentPlaceHolder : Control
    {
        protected override void Render(HtmlTextWriter writer)
        {
            ControlContent found = null;

            foreach (Control c in NamingContainer.NamingContainer.Controls)
            {
                ControlContent search;
                search = c as ControlContent;
                if (search != null && search.ControlContentPlaceHolderID.Equals(ID))
                {
                    found = search;
                    break;
                }
            }

            if (found != null)
            {                
                //write content of the ContentControl
                found.RenderControl(writer);
            }
            else
            {
                //use default content
                base.Render(writer);
            }
        }
    }
    public class ControlContent : Control
    {
        public string ControlContentPlaceHolderID { get; set; }
    }

}

example "master control" (equivalent of master page)

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MasterControl1.ascx.cs" Inherits="MasterControl1" %>
<%@ Register Namespace="MasterControls" TagPrefix="masterControls" %>

<p>content 1 below:<br />
<masterControls:ControlContentPlaceHolder ID="myContent1" runat="server">
    default content 1 here!
</masterControls:ControlContentPlaceHolder></p>

<p>content 2 below:<br />
<masterControls:ControlContentPlaceHolder ID="myContent2" runat="server">
    default content 2 here!
</masterControls:ControlContentPlaceHolder></p>

example "child control" (equivalent of page)

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ChildControl1.ascx.cs" Inherits="Control1" %>
<%@ Register Namespace="MasterControls" TagPrefix="masterControls" %>

<masterControls:ControlContent ControlContentPlaceHolderID="myContent1" runat="server">
    custom content 1
</masterControls:ControlContent>

<masterControls:ControlContent ControlContentPlaceHolderID="myContent2" runat="server">
    custom content 2
</masterControls:ControlContent>

in the code behind of the child control

using MasterControls;

//you must inherit the ChildUserControl class!
public partial class Control1 : ChildUserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    public override string MasterControlVirtualPath
    {
        //below, type the location to the master control
        //you wish to apply to this control
        get { return "~/MasterControl1.ascx"; }
    }
}
Quentinquercetin answered 23/8, 2011 at 22:9 Comment(0)
C
2

The closest thing I can suggest for what you are looking for is a templated custom control. Unfortunately, sharing controls across projects is a lot easier if those things are custom controls, without an ascx file.

Chaparral answered 3/12, 2008 at 5:9 Comment(0)
J
1

I managed to get this to work using the following code:

public class MasterLoader : UserControl
{
    MasterUserControl _masterUserControl;

    protected override void CreateChildControls()
    {
        Controls.Clear();
        base.CreateChildControls();

        Controls.Add(MasterControl);
    }

    protected override void AddedControl(Control control, int index)
    {
        if (control is MasterUserControl)
            base.AddedControl(control, index);
        else
            MasterControl.ContentArea.Controls.Add(control);
    }

    private MasterUserControl MasterControl
    {
        get
        {
            if (_masterUserControl== null)
                _masterUserControl= (MasterUserControl)LoadControl("~/MasterUserControl.ascx");

            return _masterUserControl;
        }
    }
}

Child user controls inherit from the MasterLoader class. The master user control included a placeholder control that I exposed as a public property called ContentArea.

public partial class MasterUserControl: UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    public PlaceHolder ContentArea 
    {
        get
        {
            return phContent;
        }
    }
}

Event binding and view state work as expected without any changes to any of the user controls.

Jarv answered 7/10, 2010 at 15:6 Comment(0)
C
0

Inheritance. You build the base control as a base class, and then inherit from it.

Cauterant answered 2/12, 2008 at 15:0 Comment(1)
I have done this for the code-behind side of things (i.e. my UserControl.ascx.cs file inherits from my BaseUserControl rather than System.Web.UI.UserControl. However, this does help me in terms of adding standard HTML and server controls to my base control.Ellipticity
P
0

You could also place nested user control on a place holder control in a "master" user control. Use Load method that accepts virtual path to ascx file to load appropriate control.

Predict answered 2/12, 2008 at 15:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.