我建議的解決方案如下。它有一些限制,就像所有母版頁都需要實現相同的佔位符控件集合(並不奇怪)。看一看,讓我知道你的想法。
設置我的文件夾結構是這樣的:
網站 - >模板 - > TemplateFolder(命名爲模板相同)
網站 - >模板 - >用戶控件(用戶控件都存儲在特定的非模板文件夾)
我定義它,我們可以存儲/保存/載入一個基本的模板deffinition一個簡單的模板配置類:
public class Template
{
public string TemplateName { get; set; }
public string UserControlName { get; set; }
public string MasterPageName { get; set; }
public string TemplateFolder
{
get
{
return GetTemplateFolder(TemplateName);
}
}
public string TemplateConfigFile { get { return GetTemplateConfigFile(TemplateName); } }
private static string GetTemplateFolder(string name)
{
return HttpContext.Current.Server.MapPath("~/Templates/" + name + "/");
}
private static string GetTemplateConfigFile(string name)
{
return GetTemplateFolder(name) + "/" + name + ".config";
}
public Template()
{
}
public void Save()
{
XmlSerializer xs = new XmlSerializer(typeof(Template));
if (!Directory.Exists(TemplateFolder)) Directory.CreateDirectory(TemplateFolder);
using (FileStream fs = File.OpenWrite(TemplateConfigFile))
{
xs.Serialize(fs, this);
}
}
public static Template Load(string name)
{
if(!File.Exists(GetTemplateConfigFile(name))) return null;
XmlSerializer xs = new XmlSerializer(typeof(Template));
using (FileStream fs = File.OpenRead(GetTemplateConfigFile(name)))
{
Template t = (Template)xs.Deserialize(fs);
return t;
}
}
}
你可以建立一些裸露的XML代碼上手通過運行下面的代碼:
Template t1 = new Template() { TemplateName = "Template1", MasterPageName = "Child1.master", UserControlName = "uc1.ascx" };
Template t2 = new Template() { TemplateName = "Template2", MasterPageName = "Child2.master", UserControlName = "uc2.ascx" };
t1.Save();
t2.Save();
我創建了一個基本的母版頁。除了爲您的默認頁面提供基本佔位符之外,此頁面可能永遠不會被使用。所有的母版頁都應該擁有與基本頁相同的佔位符,以便您的頁面可以互換使用它們。注意我爲我們的用戶控件留下了一個佔位符。
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="BaseMaster.master.cs" Inherits="Templates_Masters_BaseMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="cphHeader" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder id="cpUserControl" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder id="cphFooter" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
現在我創建一個使用上述母版頁的基本aspx網頁。
<%@ Page Title="" Language="C#" MasterPageFile="~/Templates/Masters/BaseMaster.master" AutoEventWireup="true" CodeFile="DefaultTemplated.aspx.cs" Inherits="DefaultTemplated" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="cphHeader" Runat="Server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="cpUserControl" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="cphFooter" Runat="Server">
</asp:Content>
在代碼隱藏中,我們將設置基本模板。這將設置主頁面並將預定義的用戶控件添加到用戶控件的內容佔位符。如果你想要,你可以製作一個面板或其他東西,並將其添加到該固定控件,但我認爲你可能會欣賞如何使它與主頁面一起工作。
public partial class DefaultTemplated : System.Web.UI.Page
{
private Template PageTemplate
{
get
{
if (_tLoaded == null)
{
string template = Request.QueryString["template"];
if (string.IsNullOrEmpty(template)) return null;
Template t = Template.Load(template);
_tLoaded = t;
}
return _tLoaded;
}
}
private Template _tLoaded = null;
protected void Page_Load(object sender, EventArgs e)
{
if (PageTemplate != null)
{
//cpUserControl is the name of my usercontrol placeholder
((ContentPlaceHolder)Page.Form.FindControl("cpUserControl")).Controls.Add(
Page.LoadControl("~/Templates/UserControls/" + PageTemplate.UserControlName));
}
}
protected void Page_PreInit(object sender, EventArgs e)
{
if (PageTemplate == null) return;
this.MasterPageFile = "~/Templates/" + PageTemplate.TemplateName + "/" + PageTemplate.MasterPageName;
}
}
如果你有一個名爲「模板」,你可以通過調用「的Default.aspx?模板=模板1」使用模板。由於您正在使用URL重寫,您將使用重寫將模板名稱作爲參數傳遞給頁面。
另一種可以與上述結合使用的方法是使用Page.ParseControl。使用這個,你可以將原始的asp.net設計器代碼(僅限設計者)存儲在數據庫或原始文本文件中。然後,你可以將它實例化加載這樣的:這個
//where pnl1 is a Panel on the page. Page.ParseControl just returns a control object, so use it anywhere.
pnl1.Controls.Add(Page.ParseControl("raw asp.net designer code here."));
一個偉大的事情是,嵌套的控制工作的偉大了。
有趣的問題......我以前已經問過自己這個問題,但是由於缺乏知識,我很快改變了我的方法。 +1或許可以啓發我。 –
「後端是完整的(現在):」我擔心你已經通過構建後端來限制你的選擇。基於框架的解決方案很可能需要重寫。 –
@ArtharAnis - 當你有機會時,讓我知道你對我的答案的看法。 – Peter