Share via


Programmgesteuertes Festlegen der Masterseite (VB)

von Scott Mitchell

Hier erfahren Sie, wie Sie die master Seite der Inhaltsseite programmgesteuert über den PreInit-Ereignishandler festlegen.

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 z. B. 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 beim Webserver eine Anforderung für eine ASP.NET Seite eingeht, bei der es sich um eine Inhaltsseite handelt, muss die ASP.NET-Engine 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 die anfänglichen Inhalts- und master Seitensteuerungshierarchien. Am Ende der PreInit-Phase werden die Inhaltssteuerelemente auf der Seite den entsprechenden ContentPlaceHolders auf der Seite master hinzugefügt (Schritt 2). Nach dieser Fusion dient die Seite master als Stamm der Fusionssteuerelementhierarchie. Diese fusionierte Steuerelementhierarchie wird dann der Seite hinzugefügt, um die fertige Steuerungshierarchie zu erstellen (Schritt 3). Das Ergebnis ist, dass die Steuerelementhierarchie der Seite die Hierarchie der fusionierten Steuerelemente enthält.

Die Steuerelementhierarchien der Gestaltungsvorlage und der Inhaltsseite werden während der PreInit-Phase miteinander verschmolzen.

Abbildung 01: Die Gestaltungsvorlage und die Steuerelementhierarchien der Inhaltsseite werden während der PreInit-Phase miteinander verschmolzen (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Schritt 2: Festlegen derMasterPageFileEigenschaft über Code

Welche master Seite an dieser Fusion beteiligt ist, hängt vom Wert der Page Eigenschaft des MasterPageFile Objekts ab. Das Festlegen des MasterPageFile Attributs in der @Page -Direktive hat den Nettoeffekt, dass die Page-Eigenschaft der - MasterPageFile Eigenschaft 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 PreInit -Ereignis aus 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.vbSie 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 Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
End Sub

Hier können wir die MasterPageFile -Eigenschaft festlegen. Aktualisieren Sie den Code, sodass er den Wert "~/Site. master" an die MasterPageFile -Eigenschaft.

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
 Me.MasterPageFile = "~/Site.master"
End Sub

Wenn Sie einen Haltepunkt festlegen und mit dem Debuggen beginnen, sehen Sie, dass der Default.aspx Ereignishandler ausgeführt wird und die MasterPageFile Eigenschaft "~/Site.master" zugewiesen wird.Page_PreInit

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 aus BasePage. Denken Sie daran, dass wir im Tutorial Angeben von Titeln, Metatags und anderen HTML-Headern im Gestaltungsvorlagen-Tutorial eine benutzerdefinierte Basisseitenklasse (BasePage) erstellt haben. Überschreibt derzeit BasePage die -Methode der Page -Klasse OnLoadComplete , in der die -Eigenschaft der Seite Title basierend auf den Siteübersichtsdaten festgelegt wird. Lassen Sie uns aktualisierenBasePage, um auch die OnPreInit -Methode außer Kraft zu setzen, um die master Seite programmgesteuert anzugeben.

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 Me.MasterPageFile = "~/Site.master" 
 MyBase.OnPreInit(e)
End Sub

Da alle unsere Inhaltsseiten von BasePageabgeleitet sind, wird ihnen jetzt die master Seite programmgesteuert zugewiesen. An diesem Punkt ist der PreInit Ereignishandler in Default.aspx.vb überflüssig. Sie können ihn entfernen.

Was ist mit der@PageRichtlinie?

Etwas verwirrend 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 -Direktive jeder Inhaltsseite @Page .

Die erste Phase im Seitenlebenszyklus ist die Initialisierungsphase. Während dieser Phase wird der Page -Eigenschaft des MasterPageFile Objekts der Wert des MasterPageFile Attributs in der @Page -Direktive zugewiesen (sofern angegeben). Die PreInit-Phase folgt der Initialisierungsphase, und hier legen wir die Eigenschaft des PageMasterPageFile Objekts programmgesteuert fest, wodurch der aus der @Page -Direktive zugewiesene Wert überschrieben wird. Da wir die Page Eigenschaft des MasterPageFile Objekts programmgesteuert festlegen, können wir das Attribut aus der MasterPageFile@Page -Direktive entfernen, ohne die Benutzererfahrung 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 Sie erwarten würden, ist die Ausgabe die gleiche wie vor dem Entfernen des Attributs.

Ob die MasterPageFile Eigenschaft über die @Page -Direktive festgelegt wird oder programmgesteuert festgelegt wird, ist für die Endbenutzererfahrung nicht relevant. Das MasterPageFile Attribut in der @Page -Direktive wird jedoch von Visual Studio während der Entwurfszeit verwendet, um die WYSIWYG-Ansicht im Designer zu erstellen. Wenn Sie in Visual Studio zu Default.aspx zurückkehren und zum Designer wird die Meldung "Gestaltungsvorlagenfehler: Die Seite verfügt über 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 Entwurfszeiterfahrung in Visual Studio zu genießen.

Visual Studio Verwendet das masterPageFile-Attribut der <span class=@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 eine Webanwendung der Blog-Engine benutzern erlauben, ein Layout für ihren Blog auszuwählen, wobei jedes Layout einer anderen master Seite zugeordnet ist. Wenn ein Besucher den Blog eines Benutzers anzeigt, muss die Webanwendung zur Laufzeit 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 seite master. Schritt 4 befasst sich mit dem Bestimmen, welche master Seite zur Laufzeit verwendet werden soll.

Erstellen Sie eine neue seite master im Stammordner namens Alternate.master. Fügen Sie der Website außerdem ein neues Stylesheet mit dem Namen AlternateStyles.csshinzu.

Hinzufügen einer weiteren Gestaltungsvorlage und einer CSS-Datei zur Website

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 Marinehintergrund angezeigt wird. Ich habe die linke Spalte ausgegeben 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 Lektionsliste gelöscht und sie durch eine horizontale Liste oberhalb MainContentvon ersetzt. Ich habe auch die Schriftarten und Farben aktualisiert, die von der master Seite verwendet werden (und damit auch deren Inhaltsseiten). Abbildung 4 zeigt Default.aspx die Verwendung der Alternate.master seite master.

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. bei Verwendung verschiedener Websteuerelemente oder eines grundlegend anderen Layouts, müssen Sie separate master Seiten verwenden. Weitere Informationen zu Designs finden Sie im Abschnitt Weiterführende Lektüre am Ende dieses Tutorials.

Unsere Inhaltsseiten können jetzt ein neues Erscheinungsbild verwenden.

Abbildung 04: Unsere Inhaltsseiten können jetzt ein neues Erscheinungsbild verwenden (Klicken Sie hier, um ein Bild in voller Größe anzuzeigen)

Wenn die master und das Inhaltsseiten-Markup verschmolzen sind, überprüft die MasterPage Klasse, ob 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. Anders ausgedrückt: Es ist zwingend erforderlich, dass die master Seite, die der Inhaltsseite zugewiesen wird, über einen ContentPlaceHolder für jedes Inhaltssteuerelement auf der Inhaltsseite verfügt.

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 der verfügbaren ContentPlaceHolders. Wenn unsere neue master Seite (Alternate.master) jemals den Inhaltsseiten zugewiesen werden kann, die Inhaltssteuerelemente für alle ContentPlaceHolders enthaltenSite.master, ist es wichtig, dass Alternate.master auch die gleichen ContentPlaceHolder-Steuerelemente wie Site.masterenthalten.

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 in 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 zu hinzu Alternate.master. Wie Sie sehen können, Alternate.master enthält vier ContentPlaceHolder-Steuerelemente mit denselben 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

Zum Testen dieses neuen master Seite die -Methode der BasePage Klasse OnPreInit aktualisieren, sodass der MasterPageFile -Eigenschaft der Wert "~/Alternate.maser" 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 zur 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 eines InvalidCastException wird beim Laden der Seite die Meldung ausgelöst: "Objekt vom Typ 'ASP.alternate_master' kann nicht in den Typ 'ASP.site_master' umgewandelt werden."

Diese Fehler treten auf, weil die Site.master CodeBehind-Klasse öffentliche Ereignisse, Eigenschaften und Methoden enthält, die nicht in Alternate.masterdefiniert 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 DetailsView-Ereignishandler ItemInserted in ~/Admin/AddProduct.aspx Code, der die lose typisierte Eigenschaft in ein Objekt vom Typ SiteumformtPage.Master. Die @MasterType -Direktive (auf diese Weise verwendet) und die Umwandlung im ItemInserted Ereignishandler koppeln die ~/Admin/AddProduct.aspx Seiten und ~/Admin/Products.aspx eng mit der Site.master master Seite.

Um diese enge Kopplung zu durchbrechen, können wir eine gemeinsame Basisklasse haben Site.master und Alternate.master daraus ableiten, die Definitionen für die öffentlichen Member enthält. Anschließend können wir die @MasterType Direktive so aktualisieren, dass sie auf diesen allgemeinen Basistyp verweist.

Erstellen einer benutzerdefinierten Basismasterseitenklasse

Fügen Sie dem Ordner eine neue Klassendatei mit dem App_Code Namen BaseMasterPage.vb hinzu, und lassen Sie sie von ableiten System.Web.UI.MasterPage. Wir müssen die RefreshRecentProductsGrid Methode und die GridMessageText Eigenschaft in BaseMasterPagedefinieren, aber wir können sie nicht einfach von Site.master dorthin verschieben, da diese Member mit Websteuerelementen arbeiten, die für die Site.master master Seite (RecentProductsGridView 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 den abgeleiteten BaseMasterPageKlassen (Site.master und Alternate.master) implementiert werden. Diese Art der Vererbung ist möglich, indem die Klasse als MustInherit und ihre Member als MustOverridegekennzeichnet werden. Kurz gesagt, das Hinzufügen dieser Schlüsselwörter zur Klasse und ihren beiden Membern gibt an, dass BaseMasterPage und nicht implementiert RefreshRecentProductsGrid wurde, GridMessageTextsondern dass die abgeleiteten Klassen dies geschieht.

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 in der .NET Framework verwendet wird, um dieses Verhalten zu erleichtern, besteht darin, ein öffentliches Ereignis in der Basisklasse zu erstellen und eine geschützte, überschreibbare Methode namens OnEventNamehinzuzufügen. Abgeleitete Klassen können dann diese Methode aufrufen, um das Ereignis auszulösen, oder es überschreiben, um Code unmittelbar vor oder nach dem Auslösen des Ereignisses auszuführen.

Aktualisieren Sie Ihre BaseMasterPage Klasse so, dass sie den folgenden Code enthält:

Public MustInherit Class BaseMasterPage 
 Inherits System.Web.UI.MasterPage 
 Public Event PricesDoubled As EventHandler
 Protected Overridable Sub OnPricesDoubled(ByVal e As EventArgs)
 RaiseEvent PricesDoubled(Me, e)
 End Sub
 Public MustOverride Sub RefreshRecentProductsGrid() 
 Public MustOverride Property GridMessageText() As String 
End Class

Wechseln Sie als Nächstes Site.master zur CodeBehind-Klasse, und lassen Sie sie von abgeleitet werden BaseMasterPage. Da BaseMasterPage elemente enthalten, die markiert sind MustOverride , müssen wir diese Member hier in Site.masterüberschreiben. Fügen Sie die Overrides Schlüsselwort (keyword) den Methoden- und Eigenschaftsdefinitionen hinzu. Aktualisieren Sie außerdem den Code, der das PricesDoubled Ereignis im Ereignishandler der DoublePrice Schaltfläche Click auslöst, mit einem Aufruf der -Methode der Basisklasse OnPricesDoubled .

Nach diesen Änderungen sollte die Site.master CodeBehind-Klasse den folgenden Code enthalten:

Partial Class Site 
 Inherits BaseMasterPage
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd")
 End Sub
 Public Overrides Sub RefreshRecentProductsGrid() 
 RecentProducts.DataBind()
 End Sub 
 Public Overrides Property GridMessageText() As String 
 Get
 Return GridMessage.Text
 End Get 
 Set(ByVal Value As String) 
 GridMessage.Text = Value 
 End Set
 End Property 
 Protected Sub DoublePrice_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DoublePrice.Click 
 ' Double the prices 
 DoublePricesDataSource.Update()
 ' Refresh RecentProducts 
 RecentProducts.DataBind()
 ' Raise the PricesDoubled event
 MyBase.OnPricesDoubled(EventArgs.Empty)
 End Sub 
End Class

Außerdem muss die CodeBehind-Klasse aktualisiert Alternate.masterwerden, damit sie von BaseMasterPage den beiden MustOverride Membern abgeleitet und überschrieben wird. Da Alternate.master jedoch keine GridView enthält, die die neuesten Produkte auflistet, noch ein Label, das eine Meldung anzeigt, nachdem ein neues Produkt der Datenbank hinzugefügt wurde, müssen diese Methoden nichts tun.

Partial Class Alternate 
 Inherits BaseMasterPage
 Public Overrides Property GridMessageText() As String 
 Get
 Return String.Empty
 End Get
 Set(ByVal value As String) 
 ' Do nothing 
 End Set 
 End Property 
 Public Overrides Sub RefreshRecentProductsGrid()
 ' Do nothing 
 End Sub 
End Class

Verweisen auf die Masterpage-Basisklasse

Nachdem wir nun 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 so zu aktualisieren, dass sie auf diesen allgemeinen Typ verweisen. Beginnen Sie mit dem Ändern der @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 hat dies zu einem Umwandlungsfehler geführt, da die Seite für die Verwendung der Alternate.master master-Seite konfiguriert ist, aber die @MasterType Direktive auf die Site.master Datei verweist. Aber jetzt wird die Seite 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.aspxvorgenommen 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:

Dim myMasterPage As Site = CType(Page.Master, Site)

Mit folgendem , der in den Basistyp umgewandelt Page.Master wird:

Dim myMasterPage As BaseMasterPage = CType(Page.Master, 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 master Seite auf einem externen Faktor zu basieren. Möglicherweise hängt die zu ladende master Seite von den Einstellungen des aktuell angemeldeten Benutzers ab. In diesem Fall müssen wir Code in die -Methode BasePage schreiben, die OnPreInit die derzeit besuchten Benutzereinstellungen für master Seite sucht.

Erstellen Sie eine Webseite, auf der der Benutzer auswählen kann, welche master Seite oder verwendet Site.masterAlternate.master werden soll, und diese Auswahl in einer Sitzungsvariablen speichern kann. Erstellen Sie zunächst eine neue Webseite im Stammverzeichnis mit dem Namen ChooseMasterPage.aspx. Beim Erstellen dieser Seite (oder anderer Inhaltsseiten) müssen Sie sie nicht an eine master Seite binden, da die master Seite programmgesteuert in BasePagefestgelegt 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 vorschlagen, die Verwendung von zu verwenden Site.master.

Hinzufügen einer Neuen Inhaltsseite zur Website

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 der <siteMapNode> für die Gestaltungsvorlagen und ASP.NET AJAX-Lektion hinzu:

<siteMapNode url="~/ChooseMasterPage.aspx" title="Choose a Master Page" />

Bevor Sie der ChooseMasterPage.aspx Seite Inhalte hinzufügen, nehmen Sie sich einen Moment Zeit, 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 MasterPageChoicefest, 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 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 besucht 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 Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 If Session("MyMasterPage") IsNot Nothing Then 
 Dim li As ListItem = MasterPageChoice.Items.FindByText(Session("MyMasterPage").ToString())
 If li IsNot Nothing Then 
 li.Selected = True
 End If 
 End If 
 End If 
End Sub

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, versucht es, das übereinstimmende ListItem in der MasterPageChoice DropDownList zu finden. Wenn ein übereinstimmende ListItem gefunden wird, wird dessen Selected Eigenschaft auf Truefestgelegt.

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 Sub SaveLayout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveLayout.Click 
 Session("MyMasterPage") = MasterPageChoice.SelectedValue 
 Response.Redirect("ChooseMasterPage.aspx")
End Sub

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. Der Response.Redirect zwingt den Browser, erneut anzufordern ChooseMasterPage.aspx.

Nach Abschluss der ChooseMasterPage.aspx Seite besteht unsere letzte Aufgabe darin, die -Eigenschaft basierend auf dem MasterPageFile Wert der MyMasterPage Session-Variablen zuzuweisenBasePage. Wenn die Sitzungsvariable nicht festgelegt ist, ist BasePage die Standardeinstellung auf Site.masterfestgelegt.

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 SetMasterPageFile() 
 MyBase.OnPreInit(e)
End Sub 
Protected Overridable Sub SetMasterPageFile() 
 Me.MasterPageFile = GetMasterPageFileFromSession() 
End Sub 
Protected Function GetMasterPageFileFromSession() As String 
 If Session("MyMasterPage") Is Nothing Then
 Return "~/Site.master"
 Else 
 Return Session("MyMasterPage").ToString() 
 End If 
End Function

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, SetMasterPageFileder von der zweiten Methode zurückgegeben wird. GetMasterPageFileFromSession Ich habe die SetMasterPageFile Methode Overridable so markiert, dass zukünftige Klassen, die erweitern BasePage , sie optional überschreiben können, um benutzerdefinierte Logik zu implementieren, falls erforderlich. Im nächsten Tutorial sehen Sie ein Beispiel für das Überschreiben BasePageSetMasterPageFile der Eigenschaft.

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.

Inhaltsseiten werden mithilfe der Website angezeigt. master Gestaltungsvorlage

Abbildung 06: Inhaltsseiten werden mithilfe der Gestaltungsvorlage Site.master angezeigt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Inhaltsseiten werden jetzt mithilfe des Alternativen angezeigt. master Gestaltungsvorlage

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 Anweisung MasterPageFile während der Initialisierungsphase zugewiesen wird. Wie dieses Tutorial gezeigt hat, können wir der MasterPageFile Eigenschaft einen Wert zuweisen, solange dies vor dem Ende der PreInit-Phase geschieht. 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 erläuterten Themen finden Sie in den folgenden Ressourcen:

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