我想要一个Master UserControl(一个主页面,但是对于UserControls)

时间:2022-08-11 15:55:42

ASP.NET master pages - essential things.

ASP.NET母版页 - 必不可少的东西。

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.

但是,我的项目中有很多非常相似的UserControls - 它可能是AJAX ModalPopup的标准布局,或更多涉及的东西。

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

我希望我可以通过一些Master UserControl来摆脱我的一些重复代码(包括ascx文件和代码隐藏)。

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

有没有人有任何方法可以实现这一目标?

5 个解决方案

#1


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.

对于你正在寻找的东西,我最接近的建议是模板化的自定义控件。不幸的是,如果这些东西是自定义控件而没有ascx文件,那么跨项目共享控件要容易得多。

#2


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:

在app_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"; }
    }
}

#3


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.

子用户控件继承自MasterLoader类。主用户控件包括一个占位符控件,我将其公开为名为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.

事件绑定和视图状态按预期工作,而不对任何用户控件进行任何更改。

#4


0  

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

遗产。您将基本控件构建为基类,然后从中继承。

#5


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.

您还可以将嵌套用户控件放在“主”用户控件中的占位符控件上。使用接受ascx文件的虚拟路径的Load方法来加载适当的控件。

#1


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.

对于你正在寻找的东西,我最接近的建议是模板化的自定义控件。不幸的是,如果这些东西是自定义控件而没有ascx文件,那么跨项目共享控件要容易得多。

#2


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:

在app_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"; }
    }
}

#3


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.

子用户控件继承自MasterLoader类。主用户控件包括一个占位符控件,我将其公开为名为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.

事件绑定和视图状态按预期工作,而不对任何用户控件进行任何更改。

#4


0  

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

遗产。您将基本控件构建为基类,然后从中继承。

#5


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.

您还可以将嵌套用户控件放在“主”用户控件中的占位符控件上。使用接受ascx文件的虚拟路径的Load方法来加载适当的控件。