Programmgesteuertes Festlegen der Masterseite (C#)
von Scott Mitchell
Hier wird die master Seite der Inhaltsseite programmgesteuert über den PreInit-Ereignishandler festgelegt.
Einführung
Seit dem ersten Beispiel in Erstellen eines Site-Wide Layouts mithilfe von Gestaltungsvorlagen haben alle Inhaltsseiten über das Attribut in der @Page
Direktive deklarativ auf ihre MasterPageFile
master Seite verwiesen. Die folgende @Page
Direktive verknüpft beispielsweise die Inhaltsseite mit der master SeiteSite.master
:
<%@ Page Language="C#" MasterPageFile="~/Site.master" ... %>
Die Page
-Klasse im System.Web.UI
Namespace enthält eine MasterPageFile
Eigenschaft, die den Pfad zur master Seite der Inhaltsseite zurückgibt. Diese Eigenschaft wird von der @Page
-Direktive festgelegt. Diese Eigenschaft kann auch verwendet werden, um die master Seite der Inhaltsseite programmgesteuert anzugeben. Dieser Ansatz ist nützlich, wenn Sie die master Seite basierend auf externen Faktoren dynamisch zuweisen möchten, z. B. der Benutzer, der die Seite besucht.
In diesem Tutorial fügen wir unserer Website eine zweite master Seite hinzu und entscheiden dynamisch, welche master Seite zur Laufzeit verwendet werden soll.
Schritt 1: Ein Blick auf den Seitenlebenszyklus
Wenn eine Anforderung auf dem Webserver für eine ASP.NET Seite eingeht, die eine Inhaltsseite ist, muss das ASP.NET-Modul die Inhaltssteuerelemente der Seite mit den entsprechenden ContentPlaceHolder-Steuerelementen der master Seite verschmelzen. Durch diese Fusion wird eine einzelne Steuerungshierarchie erstellt, die dann den typischen Seitenlebenszyklus durchlaufen kann.
Abbildung 1 veranschaulicht diese Fusion. Schritt 1 in Abbildung 1 zeigt den anfänglichen Inhalt und master Seitensteuerungshierarchien. Am Ende der PreInit-Phase werden die Inhaltssteuerelemente auf der Seite zu den entsprechenden ContentPlaceHolders auf der seite master (Schritt 2) hinzugefügt. Nach dieser Fusion dient die Seite master als Stamm der Hierarchie des fusionierten Steuerelements. Diese fusionierte Steuerelementhierarchie wird dann der Seite hinzugefügt, um die endgültige Steuerelementhierarchie zu erzeugen (Schritt 3). Das Nettoergebnis besteht darin, dass die Steuerelementhierarchie der Seite die Hierarchie des fusionierten Steuerelements enthält.
Abbildung 01: Die Gestaltungsvorlage und die Inhaltsseite-Steuerelementhierarchien werden während der PreInit-Phase miteinander verschmolzen (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 2: Festlegen derMasterPageFile
Eigenschaft über Code
Welche master Seite an dieser Fusion beteiligt ist, hängt vom Wert der -Eigenschaft des Page
MasterPageFile
Objekts ab. Das Festlegen des MasterPageFile
Attributs in der @Page
-Anweisung hat den Nettoeffekt, dass die Page
Eigenschaft der 's MasterPageFile
während der Initialisierungsphase zugewiesen wird, die die erste Phase des Lebenszyklus der Seite ist. Alternativ können wir diese Eigenschaft programmgesteuert festlegen. Es ist jedoch zwingend erforderlich, dass diese Eigenschaft festgelegt wird, bevor die Fusion in Abbildung 1 erfolgt.
Am Anfang der PreInit-Phase löst das Page
Objekt sein Ereignis aus PreInit
und ruft seine OnPreInit
-Methode auf. Um die master Seite programmgesteuert festzulegen, können wir dann entweder einen Ereignishandler für das PreInit
Ereignis erstellen oder die OnPreInit
-Methode überschreiben. Sehen wir uns beide Ansätze an.
Öffnen Default.aspx.cs
Sie zunächst die CodeBehind-Klassendatei für die Homepage unserer Website. Fügen Sie einen Ereignishandler für das Ereignis der Seite PreInit
hinzu, indem Sie den folgenden Code eingeben:
protected void Page_PreInit(object sender, EventArgs e)
{
}
Hier können wir die MasterPageFile
-Eigenschaft festlegen. Aktualisieren Sie den Code so, dass er den Wert "~/Site" zuweist. master" an die MasterPageFile
-Eigenschaft.
protected void Page_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "~/Site.master";
}
Wenn Sie einen Haltepunkt festlegen und mit dem Debuggen beginnen, sehen Sie, dass der Ereignishandler bei jedem Besuch der Default.aspx
Seite oder bei einem Postback auf dieser Seite Page_PreInit
ausgeführt wird und die MasterPageFile
Eigenschaft "~/Site.master" zugewiesen ist.
Alternativ können Sie die -Methode der Page
-Klasse OnPreInit
überschreiben und die MasterPageFile
-Eigenschaft dort festlegen. In diesem Beispiel legen wir nicht die master Seite auf einer bestimmten Seite fest, sondern in BasePage
. Denken Sie daran, dass wir im Tutorial Angeben von Titel, Metatags und anderen HTML-Headern im Gestaltungsvorlagen-Tutorial eine benutzerdefinierte Basisseitenklasse (BasePage
) erstellt haben. Derzeit BasePage
überschreibt die -Methode der Page
-Klasse OnLoadComplete
, bei der die Eigenschaft der Seite Title
basierend auf den Siteübersichtsdaten festgelegt wird. Aktualisieren wir, BasePage
um auch die OnPreInit
-Methode außer Kraft zu setzen, um die master Seite programmgesteuert anzugeben.
protected override void OnPreInit(EventArgs e)
{
this.MasterPageFile = "~/Site.master";
base.OnPreInit(e);
}
Da alle Unsere Inhaltsseiten von BasePage
abgeleitet sind, wird ihnen jetzt ihre master Seite programmgesteuert zugewiesen. An diesem Punkt ist der PreInit
Ereignishandler in Default.aspx.cs
überflüssig. Sie können ihn entfernen.
Was ist mit der@Page
Richtlinie?
Was etwas verwirrend sein kann, ist, dass die Eigenschaften der Inhaltsseiten MasterPageFile
jetzt an zwei Stellen angegeben werden: programmgesteuert in der Methode der BasePage
Klasse OnPreInit
sowie über das Attribut in der MasterPageFile
Anweisung jeder Inhaltsseite @Page
.
Die erste Phase des Seitenlebenszyklus ist die Initialisierungsphase. Während dieser Phase wird der Page
-Eigenschaft des Objekts der Wert des MasterPageFile
Attributs MasterPageFile
in der @Page
Direktive zugewiesen (sofern er angegeben wird). Die PreInit-Phase folgt der Initialisierungsphase, und hier legen wir die Eigenschaft des Page
MasterPageFile
Objekts programmgesteuert fest, wodurch der wert überschrieben wird, der aus der @Page
Direktive zugewiesen wurde. Da wir die Page
Eigenschaft des MasterPageFile
Objekts programmgesteuert festlegen, können wir das Attribut aus der MasterPageFile
@Page
Direktive entfernen, ohne die Benutzeroberfläche des Endbenutzers zu beeinträchtigen. Um sich davon zu überzeugen, entfernen Sie das Attribut aus der MasterPageFile
@Page
Direktive in Default.aspx
, und besuchen Sie die Seite dann über einen Browser. Wie zu erwarten, ist die Ausgabe die gleiche wie vor der Entfernung des Attributs.
Ob die MasterPageFile
-Eigenschaft über die @Page
-Direktive festgelegt wird oder programmgesteuert festgelegt wird, ist für die Benutzeroberfläche des Endbenutzers inkonsequent. Das MasterPageFile
Attribut in der @Page
Direktive wird jedoch während der Entwurfszeit von Visual Studio verwendet, um die WYSIWYG-Ansicht im Designer zu erstellen. Wenn Sie in Visual Studio zur Default.aspx
Designer navigieren, wird die Meldung "Gestaltungsvorlagenfehler: Die Seite enthält Steuerelemente, die einen Gestaltungsvorlagenverweis erfordern, aber keines angegeben ist" (siehe Abbildung 2).
Kurz gesagt, Sie müssen das MasterPageFile
Attribut in der @Page
Direktive belassen, um eine umfassende Entwurfszeit in Visual Studio nutzen zu können.
@Page-Direktive , um die Entwurfsansicht zu rendern" />
Abbildung 02: Visual Studio verwendet das Attribut der @Page
Direktive MasterPageFile
, um die Entwurfsansicht zu rendern (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Schritt 3: Erstellen einer alternativen Gestaltungsvorlage
Da die master Seite einer Inhaltsseite programmgesteuert zur Laufzeit festgelegt werden kann, ist es möglich, eine bestimmte master Seite basierend auf einigen externen Kriterien dynamisch zu laden. Diese Funktionalität kann in Situationen nützlich sein, in denen das Layout der Website je nach Benutzer variieren muss. Für instance kann es eine Webanwendung der Blog-Engine ihren Benutzern ermöglichen, ein Layout für ihren Blog auszuwählen, in dem jedes Layout einer anderen master Seite zugeordnet ist. Wenn ein Besucher den Blog eines Benutzers zur Laufzeit anzeigt, muss die Webanwendung das Layout des Blogs bestimmen und die entsprechende master Seite dynamisch der Inhaltsseite zuordnen.
Sehen wir uns an, wie eine master Seite zur Laufzeit basierend auf einigen externen Kriterien dynamisch geladen wird. Unsere Website enthält derzeit nur eine master Seite (Site.master
). Wir benötigen eine weitere master Seite, um die Auswahl einer master Seite zur Laufzeit zu veranschaulichen. Dieser Schritt konzentriert sich auf das Erstellen und Konfigurieren der neuen master Seite. Schritt 4 untersucht, welche master Seite zur Laufzeit verwendet werden soll.
Erstellen Sie eine neue master Seite im Stammordner mit dem Namen Alternate.master
. Fügen Sie der Website auch ein neues Stylesheet mit dem Namen AlternateStyles.css
hinzu.
Abbildung 03: Hinzufügen einer weiteren Gestaltungsvorlage und einer CSS-Datei zur Website (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Ich habe die Alternate.master
master Seite so entworfen, dass der Titel oben auf der Seite zentriert und auf einem marinen Hintergrund angezeigt wird. Ich habe die linke Spalte entfernt und diesen Inhalt unter das MainContent
ContentPlaceHolder-Steuerelement verschoben, das sich jetzt über die gesamte Breite der Seite erstreckt. Darüber hinaus habe ich die ungeordnete Lektionenliste nixed und sie durch eine horizontale Liste oben MainContent
ersetzt. Ich habe auch die Schriftarten und Farben aktualisiert, die von der master Seite verwendet werden (und damit auch die Inhaltsseiten). Abbildung 4 zeigt Default.aspx
die Verwendung der Alternate.master
master Seite.
Hinweis
ASP.NET umfasst die Möglichkeit, Designs zu definieren. Ein Design ist eine Sammlung von Bildern, CSS-Dateien und stilbezogenen Websteuerelementeigenschafteneinstellungen, die zur Laufzeit auf eine Seite angewendet werden können. Designs sind der weg, wenn sich die Layouts Ihrer Website nur in den angezeigten Bildern und ihren CSS-Regeln unterscheiden. Wenn sich die Layouts wesentlich unterscheiden, z. B. die Verwendung verschiedener Websteuerelemente oder ein radikal anderes Layout, müssen Sie separate master Seiten verwenden. Weitere Informationen zu Designs finden Sie im Abschnitt Weitere Informationen am Ende dieses Tutorials.
Abbildung 04: Unsere Inhaltsseiten können jetzt ein neues Erscheinungsbild verwenden (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Wenn das Markup der master- und Inhaltsseiten fusioniert wird, überprüft die MasterPage
Klasse, um sicherzustellen, dass jedes Content-Steuerelement auf der Inhaltsseite auf einen ContentPlaceHolder in der master Seite verweist. Eine Ausnahme wird ausgelöst, wenn ein Content-Steuerelement gefunden wird, das auf einen nicht vorhandenen ContentPlaceHolder verweist. Mit anderen Worten, es ist zwingend erforderlich, dass die master Seite, die der Inhaltsseite zugewiesen wird, über einen ContentPlaceHolder für jedes Content-Steuerelement auf der Inhaltsseite verfügen.
Die Site.master
seite master enthält vier ContentPlaceHolder-Steuerelemente:
head
MainContent
QuickLoginUI
LeftColumnContent
Einige der Inhaltsseiten unserer Website enthalten nur ein oder zwei Inhaltssteuerelemente; andere enthalten ein Content-Steuerelement für jeden verfügbaren ContentPlaceHolders. Wenn unsere neue master Seite (Alternate.master
) jemals diesen Inhaltsseiten zugewiesen wurde, die Über Content-Steuerelemente für alle ContentPlaceHolders verfügenSite.master
, ist es wichtig, dass Alternate.master
auch die gleichen ContentPlaceHolder-Steuerelemente wie Site.master
enthalten.
Damit Ihre Alternate.master
master Seite meiner ähnelt (siehe Abbildung 4), definieren Sie zunächst die Formatvorlagen der master Seite im AlternateStyles.css
Stylesheet. Fügen Sie die folgenden Regeln hinzu AlternateStyles.css
:
body
{
font-family: Comic Sans MS, Arial;
font-size: medium;
margin: 0px;
}
#topContent
{
text-align: center;
background-color: Navy;
color: White;
font-size: x-large;
text-decoration: none;
font-weight: bold;
padding: 10px;
height: 50px;
}
#topContent a
{
text-decoration: none;
color: White;
}
#navContent
{
font-size: small;
text-align: center;
}
#footerContent
{
padding: 10px;
font-size: 90%;
text-align: center;
border-top: solid 1px black;
}
#mainContent
{
text-align: left;
padding: 10px;
}
Fügen Sie als Nächstes das folgende deklarative Markup hinzu Alternate.master
. Wie Sie sehen können, Alternate.master
enthält vier ContentPlaceHolder-Steuerelemente mit den gleichen ID
Werten wie die ContentPlaceHolder-Steuerelemente in Site.master
. Darüber hinaus enthält es ein ScriptManager-Steuerelement, das für die Seiten auf unserer Website erforderlich ist, die das ASP.NET AJAX-Framework verwenden.
<!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 id="Head1" runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
<link href="AlternateStyles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="MyManager" runat="server">
</asp:ScriptManager>
<div id="topContent">
<asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx"
Text="Master Pages Tutorials" />
</div>
<div id="navContent">
<asp:ListView ID="LessonsList" runat="server"
DataSourceID="LessonsDataSource">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</LayoutTemplate>
<ItemTemplate>
<asp:HyperLink runat="server" ID="lnkLesson"
NavigateUrl='<%# Eval("Url") %>'
Text='<%# Eval("Title") %>' />
</ItemTemplate>
<ItemSeparatorTemplate> | </ItemSeparatorTemplate>
</asp:ListView>
<asp:SiteMapDataSource ID="LessonsDataSource" runat="server"
ShowStartingNode="false" />
</div>
<div id="mainContent">
<asp:ContentPlaceHolder id="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
<div id="footerContent">
<p>
<asp:Label ID="DateDisplay" runat="server"></asp:Label>
</p>
<asp:ContentPlaceHolder ID="QuickLoginUI" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="LeftColumnContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Testen der neuen Gestaltungsvorlage
Um diese neue master Seite zu testen, aktualisieren Sie die Methode der BasePage
KlasseOnPreInit
, sodass der MasterPageFile
Eigenschaft der Wert "~/Alternate.master" zugewiesen wird, und besuchen Sie dann die Website. Jede Seite sollte ohne Fehler funktionieren, mit Ausnahme von zwei: ~/Admin/AddProduct.aspx
und ~/Admin/Products.aspx
. Das Hinzufügen eines Produkts zu DetailsView in ~/Admin/AddProduct.aspx
führt zu einer NullReferenceException
aus der Codezeile, die versucht, die Eigenschaft der master Seite GridMessageText
festzulegen. Beim Aufrufen ~/Admin/Products.aspx
einer InvalidCastException
wird beim Laden der Seite mit der Meldung "Objekt vom Typ 'ASP.alternate_master' kann nicht in den Typ 'ASP.site_master' umgewandelt werden' ausgelöst."
Diese Fehler treten auf, weil die Site.master
CodeBehind-Klasse öffentliche Ereignisse, Eigenschaften und Methoden enthält, die nicht in Alternate.master
definiert sind. Der Markupteil dieser beiden Seiten verfügt über eine @MasterType
-Direktive, die auf die Site.master
master Seite verweist.
<%@ MasterType VirtualPath="~/Site.master" %>
Außerdem enthält der Ereignishandler von ItemInserted
DetailsView in ~/Admin/AddProduct.aspx
Code, der die lose typisierte Eigenschaft in ein Objekt vom Typ Site
wandeltPage.Master
. Die @MasterType
-Direktive (auf diese Weise verwendet) und die Umwandlung im ItemInserted
Ereignishandler verknüpfen die ~/Admin/AddProduct.aspx
Seiten und ~/Admin/Products.aspx
eng mit der Site.master
seite master.
Um diese enge Kopplung zu unterbrechen, können Site.master
wir eine gemeinsame Basisklasse haben, Alternate.master
die Definitionen für die öffentlichen Member enthält. Danach können wir die @MasterType
-Direktive aktualisieren, um auf diesen allgemeinen Basistyp zu verweisen.
Erstellen einer benutzerdefinierten Masterpage-Basisklasse
Fügen Sie dem Ordner eine neue Klassendatei mit dem App_Code
Namen BaseMasterPage.cs
hinzu, und lassen Sie sie von abgeleitet werden System.Web.UI.MasterPage
. Wir müssen die RefreshRecentProductsGrid
Methode und die GridMessageText
Eigenschaft in BaseMasterPage
definieren, aber wir können sie nicht einfach aus Site.master
dorthin verschieben, da diese Member mit Websteuerelementen arbeiten, die für die Site.master
master Seite (GridView RecentProducts
und GridMessage
Label) spezifisch sind.
Was wir tun müssen, ist, so zu konfigurieren BaseMasterPage
, dass diese Member dort definiert sind, aber tatsächlich von BaseMasterPage
den abgeleiteten Klassen (Site.master
und Alternate.master
) implementiert werden. Diese Art der Vererbung ist möglich, indem die -Klasse und ihre Member als abstract
gekennzeichnet werden. Kurz gesagt, das Hinzufügen des abstract
Schlüsselwort (keyword) zu diesen beiden Membern gibt an, dass BaseMasterPage
und GridMessageText
nicht implementiert RefreshRecentProductsGrid
wurde, sondern dass die abgeleiteten Klassen dies ausführen.
Außerdem müssen wir das PricesDoubled
Ereignis in BaseMasterPage
definieren und von den abgeleiteten Klassen ein Mittel bereitstellen, um das Ereignis auszulösen. Das Muster, das im .NET Framework verwendet wird, um dieses Verhalten zu erleichtern, besteht darin, virtual
ein öffentliches Ereignis in der Basisklasse zu erstellen und eine geschützte Methode namens OnEventName
hinzuzufügen. Abgeleitete Klassen können dann diese Methode aufrufen, um das Ereignis auszulösen, oder sie überschreiben, um Code unmittelbar vor oder nach dem Auslösen des Ereignisses auszuführen.
Aktualisieren Sie Ihre BaseMasterPage
Klasse, sodass sie den folgenden Code enthält:
using System; public abstract class BaseMasterPage : System.Web.UI.MasterPage
{
public event EventHandler PricesDoubled;
protected virtual void OnPricesDoubled(EventArgs e)
{
if (PricesDoubled != null)
PricesDoubled(this, e);
}
public abstract void RefreshRecentProductsGrid();
public abstract string GridMessageText
{
get;
set;
}
}
Wechseln Sie als Nächstes Site.master
zur CodeBehind-Klasse, und lassen Sie sie von abgeleitet werden BaseMasterPage
. Da BaseMasterPage
müssen abstract
wir diese abstract
Member hier in Site.master
überschreiben. Fügen Sie die override
Schlüsselwort (keyword) den Methoden- und Eigenschaftendefinitionen hinzu. Aktualisieren Sie außerdem den Code, der das PricesDoubled
Ereignis im Ereignishandler des Click
DoublePrice
Button-Objekts auslöst, mit einem Aufruf der -Methode der BasisklasseOnPricesDoubled
.
Nach diesen Änderungen sollte die Site.master
CodeBehind-Klasse den folgenden Code enthalten:
public partial class Site : BaseMasterPage {
protected void Page_Load(object sender, EventArgs e)
{
DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd");
}
public override void RefreshRecentProductsGrid()
{
RecentProducts.DataBind();
}
public override string GridMessageText
{
get
{
return GridMessage.Text;
}
set
{
GridMessage.Text = value;
}
}
protected void DoublePrice_Click(object sender, EventArgs e)
{
// Double the prices
DoublePricesDataSource.Update();
// Refresh RecentProducts
RecentProducts.DataBind();
// Raise the PricesDoubled event
base.OnPricesDoubled(EventArgs.Empty);
}
}
Außerdem müssen Alternate.master
wir die CodeBehind-Klasse aktualisieren, um von BaseMasterPage
den beiden abstract
Membern abzuleiten und sie zu überschreiben. Da Alternate.master
jedoch keine GridView enthält, die die neuesten Produkte auflistet, noch ein Label, das eine Meldung anzeigt, nachdem ein neues Produkt zur Datenbank hinzugefügt wurde, müssen diese Methoden nichts tun.
public partial class Alternate : BaseMasterPage
{
public override void RefreshRecentProductsGrid()
{
// Do nothing
}
public override string GridMessageText
{
get
{
return string.Empty;
}
set
{
// Do nothing
}
}
}
Verweisen auf die Masterpage-Basisklasse
Nachdem wir die BaseMasterPage
Klasse abgeschlossen haben und unsere beiden master Seiten erweitert haben, besteht unser letzter Schritt darin, die ~/Admin/AddProduct.aspx
Seiten und ~/Admin/Products.aspx
zu aktualisieren, um auf diesen allgemeinen Typ zu verweisen. Ändern Sie zunächst die @MasterType
-Direktive auf beiden Seiten von:
<%@ MasterType VirtualPath="~/Site.master" %>
Nach:
<%@ MasterType TypeName="BaseMasterPage" %>
Anstatt auf einen Dateipfad zu verweisen, verweist die @MasterType
Eigenschaft jetzt auf den Basistyp (BaseMasterPage
). Folglich ist die stark typisierte Master
Eigenschaft, die in den CodeBehind-Klassen beider Seiten verwendet wird, jetzt vom Typ BaseMasterPage
(anstelle des Typs Site
). Mit dieser Änderung können Sie erneut besuchen ~/Admin/Products.aspx
. Zuvor führte dies zu einem Umwandlungsfehler, da die Seite für die Verwendung der Alternate.master
master-Seite konfiguriert ist, aber die @MasterType
Direktive auf die Site.master
Datei verwiesen hat. Jetzt wird die Seite jedoch ohne Fehler gerendert. Dies liegt daran, dass die Alternate.master
master Seite in ein Objekt vom Typ BaseMasterPage
umgewandelt werden kann (da es erweitert wird).
Es gibt eine kleine Änderung, die in ~/Admin/AddProduct.aspx
vorgenommen werden muss. Der Ereignishandler des ItemInserted
DetailsView-Steuerelements verwendet sowohl die stark typisierte Master
Eigenschaft als auch die lose typisierte Page.Master
Eigenschaft. Wir haben den stark typisierten Verweis behoben, als wir die @MasterType
-Direktive aktualisiert haben, aber wir müssen den lose typisierten Verweis trotzdem aktualisieren. Ersetzen Sie die folgende Codezeile:
Site myMasterPage = Page.Master as Site;
Mit folgendem , der in den Basistyp umgewandelt wird Page.Master
:
BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;
Schritt 4: Bestimmen, welche Gestaltungsvorlage an die Inhaltsseiten gebunden werden soll
Unsere BasePage
-Klasse legt derzeit die Eigenschaften aller Inhaltsseiten MasterPageFile
auf einen hartcodierten Wert in der PreInit-Phase des Seitenlebenszyklus fest. Wir können diesen Code aktualisieren, um die seite master auf einem externen Faktor zu basieren. Möglicherweise hängt die master Seite, die geladen werden soll, von den Einstellungen des derzeit angemeldeten Benutzers ab. In diesem Fall müssten wir Code in die -Methode BasePage
schreiben, die OnPreInit
die master Seiteneinstellungen des aktuell besuchenden Benutzers sucht.
Erstellen Wir nun eine Webseite, auf der der Benutzer auswählen kann, welche master Seite verwendet werden soll ( Site.master
oder Alternate.master
) und diese Auswahl in einer Sitzungsvariablen speichern kann. Erstellen Sie zunächst eine neue Webseite im Stammverzeichnis namens ChooseMasterPage.aspx
. Wenn Sie diese Seite (oder fortan andere Inhaltsseiten) erstellen, müssen Sie sie nicht an eine master-Seite binden, da die master Seite programmgesteuert in BasePage
festgelegt wird. Wenn Sie die neue Seite jedoch nicht an eine master Seite binden, enthält das standardmäßige deklarative Markup der neuen Seite ein Webformular und andere Inhalte, die von der master Seite bereitgestellt werden. Sie müssen dieses Markup manuell durch die entsprechenden Inhaltssteuerelemente ersetzen. Aus diesem Grund finde ich es einfacher, die neue ASP.NET-Seite an eine master-Seite zu binden.
Hinweis
Da Site.master
und Alternate.master
über denselben Satz von ContentPlaceHolder-Steuerelementen verfügen, spielt es keine Rolle, welche master Seite Sie beim Erstellen der neuen Inhaltsseite auswählen. Aus Gründen der Konsistenz würde ich die Verwendung von vorschlagen Site.master
.
Abbildung 05: Hinzufügen einer neuen Inhaltsseite zur Website (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Aktualisieren Sie die Web.sitemap
Datei so, dass sie einen Eintrag für diese Lektion enthält. Fügen Sie das folgende Markup unter dem <siteMapNode>
für die Gestaltungsvorlagen und ASP.NET AJAX-Lektion hinzu:
<siteMapNode url="~/ChooseMasterPage.aspx" title="Choose a Master Page" />
Vor dem Hinzufügen von Inhalten zur Seite nehmen Sie sich einen Moment Zeit, ChooseMasterPage.aspx
um die CodeBehind-Klasse der Seite zu aktualisieren, sodass sie von (statt System.Web.UI.Page
) BasePage
abgeleitet wird. Fügen Sie als Nächstes der Seite ein DropDownList-Steuerelement hinzu, legen Sie dessen ID
Eigenschaft auf MasterPageChoice
fest, und fügen Sie zwei ListItems mit den Text
Werten "~/Site.master" und "~/Alternate.master" hinzu.
Fügen Sie der Seite ein Button-Websteuerelement hinzu, und legen Sie dessen ID
Eigenschaften und Text
auf SaveLayout
bzw. "Layoutauswahl speichern" fest. An diesem Punkt sollte das deklarative Markup Ihrer Seite in etwa wie folgt aussehen:
<p>
Your layout choice:
<asp:DropDownList ID="MasterPageChoice" runat="server">
<asp:ListItem>~/Site.master</asp:ListItem>
<asp:ListItem>~/Alternate.master</asp:ListItem>
</asp:DropDownList>
</p>
<p>
<asp:Button ID="SaveLayout" runat="server" Text="Save Layout Choice" />
</p>
Wenn die Seite zum ersten Mal aufgerufen wird, müssen wir die aktuell ausgewählte master Seitenauswahl des Benutzers anzeigen. Erstellen Sie einen Page_Load
Ereignishandler, und fügen Sie den folgenden Code hinzu:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Session["MyMasterPage"] != null)
{
ListItem li = MasterPageChoice.Items.FindByText(Session["MyMasterPage"].ToString());
if (li != null)
li.Selected = true;
}
}
}
Der obige Code wird nur beim ersten Seitenbesuch (und nicht bei nachfolgenden Postbacks) ausgeführt. Zuerst wird überprüft, ob die Sitzungsvariable MyMasterPage
vorhanden ist. Wenn dies der Fall ist, wird versucht, das übereinstimmende ListItem in der MasterPageChoice
DropDownList zu finden. Wenn ein übereinstimmende ListItem gefunden wird, wird dessen Selected
Eigenschaft auf true
festgelegt.
Außerdem benötigen wir Code, der die Auswahl des Benutzers in der MyMasterPage
Sitzungsvariablen speichert. Erstellen Sie einen Ereignishandler für das SaveLayout
Button-Ereignis Click
, und fügen Sie den folgenden Code hinzu:
protected void SaveLayout_Click(object sender, EventArgs e)
{
Session["MyMasterPage"] = MasterPageChoice.SelectedValue;
Response.Redirect("ChooseMasterPage.aspx");
}
Hinweis
Zu dem Zeitpunkt, zu dem der Click
Ereignishandler beim Postback ausgeführt wird, wurde die Seite master bereits ausgewählt. Daher wird die Dropdownliste des Benutzers erst beim nächsten Seitenbesuch wirksam. Erzwingt Response.Redirect
den Browser, erneut anzufordern ChooseMasterPage.aspx
.
Nach Abschluss der ChooseMasterPage.aspx
Seite besteht unsere letzte Aufgabe darin, die MasterPageFile
-Eigenschaft basierend auf dem Wert der MyMasterPage
Sitzungsvariablen zuzuweisenBasePage
. Wenn die Sitzungsvariable nicht festgelegt ist, haben Sie BasePage
den Standardwert auf Site.master
.
protected override void OnPreInit(EventArgs e)
{
SetMasterPageFile();
base.OnPreInit(e);
}
protected virtual void SetMasterPageFile()
{
this.MasterPageFile = GetMasterPageFileFromSession();
}
protected string GetMasterPageFileFromSession()
{
if (Session["MyMasterPage"] == null)
return "~/Site.master";
else
return Session["MyMasterPage"].ToString();
}
Hinweis
Ich habe den Code, der die Page
Eigenschaft des MasterPageFile
Objekts zuweist, aus dem OnPreInit
Ereignishandler in zwei separate Methoden verschoben. Diese erste Methode weist die -Eigenschaft dem MasterPageFile
Wert zu, SetMasterPageFile
der von der zweiten Methode zurückgegeben wird. GetMasterPageFileFromSession
Ich habe die SetMasterPageFile
-Methode virtual
so erstellt, dass zukünftige Klassen, die erweitern BasePage
, sie optional überschreiben können, um bei Bedarf benutzerdefinierte Logik zu implementieren. Ein Beispiel für das Überschreiben BasePage
der -Eigenschaft finden SetMasterPageFile
Sie im nächsten Tutorial.
Wenn dieser Code vorhanden ist, besuchen Sie die ChooseMasterPage.aspx
Seite. Zunächst ist die Site.master
Seite master ausgewählt (siehe Abbildung 6), aber der Benutzer kann eine andere master Seite aus der Dropdownliste auswählen.
Abbildung 06: Inhaltsseiten werden mithilfe der Gestaltungsvorlage Site.master
angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 07: Inhaltsseiten werden jetzt mithilfe der Gestaltungsvorlage Alternate.master
angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Zusammenfassung
Wenn eine Inhaltsseite besucht wird, werden ihre Inhaltssteuerelemente mit den ContentPlaceHolder-Steuerelementen der master Seite verschmolzen. Die master Seite der Inhaltsseite wird durch die -Eigenschaft der Page
-Klasse MasterPageFile
bezeichnet, die dem Attribut der @Page
Direktive MasterPageFile
während der Initialisierungsphase zugewiesen wird. Wie in diesem Tutorial gezeigt, können wir der MasterPageFile
Eigenschaft einen Wert zuweisen, solange dies vor dem Ende der PreInit-Phase der Fall ist. Die Möglichkeit, die master Seite programmgesteuert anzugeben, öffnet die Tür für komplexere Szenarien, z. B. das dynamische Binden einer Inhaltsseite an eine master-Seite basierend auf externen Faktoren.
Viel Spaß beim Programmieren!
Weitere Informationen
Weitere Informationen zu den in diesem Tutorial behandelten Themen finden Sie in den folgenden Ressourcen:
- ASP.NET-Seiten-Lebenszyklusdiagramm
- Übersicht über den ASP.NET-Seitenlebenszyklus
- Übersicht über ASP.NET Designs und Skins
- Gestaltungsvorlagen: Tipps, Tricks und Fallen
- Designs in ASP.NET
Zum Autor
Scott Mitchell, Autor mehrerer ASP/ASP.NET-Bücher und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 3.5 in 24 Stunden. Scott kann unter mitchell@4GuysFromRolla.com oder über seinen Blog unter http://ScottOnWriting.NETerreicht werden.
Besonderen Dank an
Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Lead Reviewer für dieses Tutorial war Suchi Banerjee. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie mir eine Zeile unter mitchell@4GuysFromRolla.com
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für