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?
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"; }
}
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With