Moje proponowane rozwiązanie znajduje się poniżej. Ma kilka ograniczeń, tak jak wszystkie strony wzorcowe muszą implementować ten sam zestaw formantów symboli zastępczych (co nie jest zaskakujące). Spójrz i daj mi znać, co myślisz.
mogę skonfigurować mój struktura folderów tak:
WWW -> Szablony -> TemplateFolder (nazwany tak samo jak w szablonie)
WWW -> Szablony -> UserControls (kontrola użytkownika są przechowywane w non-szablonu określonego folder)
ja zdefiniował prosty szablon klasy konfiguracji, które możemy przechowywać/zapisać/załadować podstawowego szablonu 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;
}
}
}
można zbudować jakąś gołą kodu xml, aby zacząć za pomocą kodu poniżej:
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();
Utworzono podstawową stronę wzorcową. Ta strona prawdopodobnie nigdy nie będzie używana, z wyjątkiem tego, że domyślna strona będzie podstawowym symbolem zastępczym. Wszystkie strony wzorcowe powinny mieć taki sam zestaw symboli zastępczych jak podstawowy, aby strony mogły z nich korzystać w sposób wymierny. Uwaga Zostawiłem symbol zastępczy dla naszej kontroli użytkownika.
<%@ 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>
Teraz tworzę podstawową stronę internetową ASPX, która korzysta z powyższej strony wzorcowej.
<%@ 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>
W ustawieniu kodu ustawimy podstawowe szablon. Spowoduje to ustawienie strony wzorcowej i dodanie wstępnie zdefiniowanej kontroli użytkownika do symbolu zastępczego zawartości dla formantów użytkownika. Jeśli chcesz, możesz po prostu utworzyć panel lub coś takiego i dodać go do tej stałej kontroli, ale pomyślałem, że możesz docenić, jak sprawić, by działał on ze stronami wzorcowymi.
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;
}
}
Jeśli masz szablon o nazwie "Szablon1", możesz go użyć, wywołując "Default.aspx? Template = Template1". Ponieważ korzystasz z przepisywania adresów URL, możesz użyć przepisania, aby przekazać nazwę szablonu jako parametr do strony.
Inną opcją, która mogłaby być łączona z powyższym, byłoby użycie Page.ParseControl. Używając tego, możesz przechowywać swój surowy kod projektanta asp.net (tylko projektant) w bazie danych lub w surowym pliku tekstowym. Następnie można go utworzyć w następujący sposób:
//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."));
Jedną z wielkich zalet jest to, że kontrolki zagnieżdżone również działają świetnie.
Interesujące pytanie ... Już wcześniej zadawałem sobie to pytanie, ale szybko zmieniłem podejście ze względu na brak wiedzy. +1 może mnie oświecić. –
"Backend jest kompletny (na razie):" Obawiam się, że ograniczyłeś już swoje wybory, budując już back-end. Rozwiązanie oparte na strukturze ramowej najprawdopodobniej wymagałoby przepisania. –
@ArtharAnis - Kiedy masz szansę, daj mi znać, co myślisz o mojej odpowiedzi. – Peter