Freigeben über


Programmgesteuertes Festlegen der Masterseite (C#)

von Scott Mitchell

Es wird untersucht, wie die Gestaltungsvorlage der Inhaltsseite programmgesteuert über den PreInit-Ereignishandler festgelegt wird.

Einführung

Da im ersten Beispiel beim Erstellen eines websiteweiten Layouts mithilfe von Gestaltungsvorlagen auf alle Inhaltsseiten deklarativ über das MasterPageFile Attribut in der @Page Direktive verwiesen wurde, haben alle Inhaltsseiten deklarativ auf ihre Gestaltungsvorlage verwiesen. Die folgende @Page Direktive verknüpft beispielsweise die Inhaltsseite mit der Gestaltungsvorlage Site.master:

<%@ Page Language="C#" MasterPageFile="~/Site.master" ... %>

Die Klasse im Namespace enthält eineMasterPageFile Eigenschaft, die den Pfad zur Gestaltungsvorlage der Inhaltsseite zurückgibt. Dies ist diese Eigenschaft, die von der @Page Direktive festgelegt wird.System.Web.UIPage Diese Eigenschaft kann auch verwendet werden, um die Gestaltungsvorlage der Inhaltsseite programmgesteuert anzugeben. Dieser Ansatz ist nützlich, wenn Sie die Gestaltungsvorlage basierend auf externen Faktoren dynamisch zuweisen möchten, z. B. den Benutzer, der die Seite besucht.

In diesem Lernprogramm fügen wir unserer Website eine zweite Gestaltungsvorlage hinzu und entscheiden dynamisch, welche Gestaltungsvorlage 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 modul ASP.NET die Inhaltssteuerelemente der Seite in den entsprechenden ContentPlaceHolder-Steuerelementen der Gestaltungsvorlage gliedern. Diese Fusion erstellt eine einzelne Steuerelementhierarchie, die dann den typischen Seitenlebenszyklus durchlaufen kann.

Abbildung 1 veranschaulicht diese Fusion. Schritt 1 in Abbildung 1 zeigt die Hierarchien der anfänglichen Inhalts- und Gestaltungsvorlagensteuerelemente. Am Ende der PreInit-Phase werden die Inhaltssteuerelemente auf der Seite den entsprechenden ContentPlaceHolders in der Gestaltungsvorlage (Schritt 2) hinzugefügt. Nach dieser Fusion dient die Gestaltungsvorlage als Stamm der Fused-Steuerelementhierarchie. Diese Fused-Steuerelementhierarchie wird dann der Seite hinzugefügt, um die endgültige Steuerelementhierarchie (Schritt 3) zu erzeugen. Das Nettoergebnis besteht darin, dass die Steuerelementhierarchie der Seite die Fused-Steuerelementhierarchie enthält.

Die Steuerelementhierarchien der Gestaltungsvorlage und der Inhaltsseite werden während der PreInit-Phase miteinander zusammengeführt.

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

Schritt 2: Festlegen derMasterPageFileEigenschaft aus Code

Welche Gestaltungsvorlagenpartaks in dieser Fusion enthalten sind, hängt vom Wert der Eigenschaft des Page MasterPageFile Objekts ab. Das Festlegen des MasterPageFile Attributs in der @Page Direktive hat die Nettowirkung der Zuweisung der PageEigenschaft MasterPageFile während der Initialisierungsphase, die die erste Phase des Lebenszyklus der Seite ist. Wir können diese Eigenschaft auch programmgesteuert festlegen. Es ist jedoch zwingend erforderlich, dass diese Eigenschaft vor der Fusion in Abbildung 1 festgelegt wird.

Am Anfang der PreInit-Phase löst das Page Objekt sein PreInit Ereignis aus und ruft seine OnPreInit Methode auf. Um die Gestaltungsvorlage programmgesteuert festzulegen, können wir entweder einen Ereignishandler für das PreInit Ereignis erstellen oder die OnPreInit Methode außer Kraft setzen. Sehen wir uns beide Ansätze an.

Default.aspx.csÖffnen 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) 
{ 
}

Von hier aus können wir die MasterPageFile Eigenschaft festlegen. Aktualisieren Sie den Code so, dass er der Eigenschaft den Wert "~/Site.master" zuweist MasterPageFile .

protected void Page_PreInit(object sender, EventArgs e) 
{
    this.MasterPageFile = "~/Site.master"; 
}

Wenn Sie einen Haltepunkt festlegen und mit dem Debuggen beginnen, wird angezeigt, dass immer, wenn die Default.aspx Seite besucht wird oder wenn ein Postback zu dieser Seite vorhanden ist, der Page_PreInit Ereignishandler 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 die Gestaltungsvorlage nicht auf einer bestimmten Seite fest, sondern aus BasePage. Erinnern Sie sich daran, dass wir eine benutzerdefinierte Basisseitenklasse (BasePage) wieder im Lernprogramm "Titel", "Metatags" und "Andere HTML-Kopfzeilen" erstellt haben. Überschreibt derzeit BasePage die Methode der Page Klasse OnLoadComplete , wobei sie die Eigenschaft der Seite Title basierend auf den Websitezuordnungsdaten festlegt. Aktualisieren wir, um die Methode auch zu überschreiben, um die OnPreInit Gestaltungsvorlage BasePage programmgesteuert anzugeben.

protected override void OnPreInit(EventArgs e) 
{ 
    this.MasterPageFile = "~/Site.master"; 
    base.OnPreInit(e); 
}

Da alle unsere Inhaltsseiten von BasePage abgeleitet sind, werden ihnen alle jetzt programmgesteuert ihre Gestaltungsvorlage zugewiesen. An diesem Punkt ist der PreInit Ereignishandler Default.aspx.cs überflüssig. Sie können ihn entfernen.

Was ist mit der@PageRichtlinie?

Möglicherweise ist es etwas verwirrend, dass die Eigenschaften der Inhaltsseiten MasterPageFile nun 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. In dieser Phase wird die Page Eigenschaft des Objekts dem Wert des MasterPageFile Attributs MasterPageFile in der @Page Direktive (sofern angegeben) zugewiesen. Die PreInit-Phase folgt der Initialisierungsstufe, und hier legen wir die Eigenschaft des Page MasterPageFile Objekts programmgesteuert fest, wodurch der wert aus der @Page Direktive überschrieben wird. Da wir die Eigenschaft des Page MasterPageFile Objekts programmgesteuert festlegen, könnten wir das MasterPageFile Attribut aus der @Page Direktive entfernen, ohne die Benutzererfahrung des Endbenutzers zu beeinträchtigen. Um sich davon zu überzeugen, entfernen Sie das MasterPageFile Attribut aus der @Page Direktive, Default.aspx und besuchen Sie dann die Seite über einen Browser. Wie Sie erwarten, ist die Ausgabe identisch mit dem, bevor das Attribut entfernt wurde.

Gibt an, ob die MasterPageFile Eigenschaft über die @Page Direktive festgelegt wird oder programmgesteuert inkonsequent für die Benutzeroberfläche des Endbenutzers ist. MasterPageFile Das Attribut in der Direktive wird jedoch während der @Page Entwurfszeit von Visual Studio verwendet, um die WYSIWYG-Ansicht im Designer zu erstellen. Wenn Sie in Visual Studio zurückkehren Default.aspx und zum Designer navigieren, wird die Meldung "Gestaltungsvorlagenfehler: Die Seite enthält Steuerelemente, für die ein Gestaltungsvorlagenverweis erforderlich ist, aber keine 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 zu genießen.

Visual Studio verwendet die klasse <span=@Page MasterPageFile-Attribut der Direktive zum Rendern der Entwurfsansicht" />

Abbildung 02: Visual Studio verwendet das @Page Direktive-Attribut MasterPageFile zum Rendern der Entwurfsansicht (Klicken, um das Bild in voller Größe anzuzeigen)

Schritt 3: Erstellen einer alternativen Gestaltungsvorlage

Da die Gestaltungsvorlage einer Inhaltsseite zur Laufzeit programmgesteuert festgelegt werden kann, ist es möglich, eine bestimmte Gestaltungsvorlage 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. Eine Blogmodul-Webanwendung kann es benutzern beispielsweise ermöglichen, ein Layout für ihren Blog auszuwählen, in dem jedes Layout einer anderen Gestaltungsvorlage zugeordnet ist. Zur Laufzeit muss die Webanwendung, wenn ein Besucher den Blog eines Benutzers anzeigt, das Layout des Blogs ermitteln und die entsprechende Gestaltungsvorlage dynamisch der Inhaltsseite zuordnen.

Sehen wir uns an, wie eine Gestaltungsvorlage zur Laufzeit basierend auf einigen externen Kriterien dynamisch geladen wird. Unsere Website enthält derzeit nur eine Gestaltungsvorlage (Site.master). Wir benötigen eine weitere Gestaltungsvorlage, um die Auswahl einer Gestaltungsvorlage zur Laufzeit zu veranschaulichen. Dieser Schritt konzentriert sich auf das Erstellen und Konfigurieren der neuen Gestaltungsvorlage. In Schritt 4 wird untersucht, welche Gestaltungsvorlage zur Laufzeit verwendet werden soll.

Erstellen Sie eine neue Gestaltungsvorlage im Stammordner mit dem Namen Alternate.master. Fügen Sie der Website auch ein neues Stylesheet mit dem Namen hinzu AlternateStyles.css.

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 Gestaltungsvorlage so entworfen, dass der Titel oben auf der Seite angezeigt wird, zentriert und auf einem Marinehintergrund. Ich habe die linke Spalte weggelassen und diesen Inhalt unter das MainContent ContentPlaceHolder-Steuerelement verschoben, der nun die gesamte Breite der Seite umfasst. Darüber hinaus habe ich die ungeordnete Unterrichtsliste nixiert und durch eine horizontale Liste oben MainContentersetzt. Außerdem habe ich die Schriftarten und Farben aktualisiert, die von der Gestaltungsvorlage (und durch Erweiterung, deren Inhaltsseiten) verwendet werden. Abbildung 4 zeigt Default.aspx die Verwendung der Gestaltungsvorlage Alternate.master .

Hinweis

ASP.NET umfasst die Möglichkeit, Designs zu definieren. Ein Design ist eine Sammlung von Bildern, CSS-Dateien und stilbezogenen Websteuerelement-Eigenschafteneinstellungen, die zur Laufzeit auf eine Seite angewendet werden können. Designs sind die Möglichkeit, zu gehen, 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 unterschiedlicher Websteuerelemente oder ein radikal anderes Layout, müssen Sie separate Gestaltungsvorlagen verwenden. Weitere Informationen zu Designs finden Sie im Abschnitt "Weiteres Lesen" am Ende dieses Lernprogramms.

Unsere Inhaltsseiten können jetzt ein neues Aussehen und Verhalten verwenden

Abbildung 04: Unsere Inhaltsseiten können jetzt ein neues Aussehen und Verhalten 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, ob jedes Inhaltssteuerelement auf der Inhaltsseite auf einen ContentPlaceHolder in der Gestaltungsvorlage verweist. Eine Ausnahme wird ausgelöst, wenn ein Inhaltssteuerelement gefunden wird, das auf einen nicht vorhandenen ContentPlaceHolder verweist. Mit anderen Worten, es ist zwingend erforderlich, dass die Gestaltungsvorlage, die der Inhaltsseite zugewiesen wird, einen ContentPlaceHolder für jedes Inhaltssteuerelement auf der Inhaltsseite aufweist.

Die Gestaltungsvorlage Site.master enthält vier ContentPlaceHolder-Steuerelemente:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

Einige der Inhaltsseiten auf unserer Website umfassen nur ein oder zwei Inhaltssteuerelemente; andere enthalten ein Inhaltssteuerelement für jeden der verfügbaren ContentPlaceHolders. Wenn unsere neue Gestaltungsvorlage (Alternate.master) möglicherweise jemals diesen Inhaltsseiten zugewiesen wird, die Inhaltssteuerelemente für alle ContentPlaceHolders Site.master enthalten, ist es wichtig, dass Alternate.master auch dieselben ContentPlaceHolder-Steuerelemente enthalten sind wie Site.master.

Um ihre Alternate.master Gestaltungsvorlage so zu gestalten, dass sie ähnlich wie meine (siehe Abbildung 4) aussieht, definieren Sie zunächst die Formatvorlagen der Gestaltungsvorlage 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 zu Alternate.master. Enthält, wie Sie sehen können, Alternate.master 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 diese 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 Gestaltungsvorlage OnPreInit zu testen, aktualisieren Sie die Methode der BasePage Klasse so, dass 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 zur DetailsView führt zu ~/Admin/AddProduct.aspx einer NullReferenceException Codezeile, die versucht, die Eigenschaft der Gestaltungsvorlage GridMessageText festzulegen. Beim Aufrufen eines Vorgangs ~/Admin/Products.aspx wird das Laden der InvalidCastException Seite mit der Meldung ausgelöst: "Objekt vom Typ 'ASP.alternate_master' kann nicht in den Typ 'ASP.site_master' umwandeln."

Diese Fehler treten auf, da die Site.master CodeBehind-Klasse öffentliche Ereignisse, Eigenschaften und Methoden enthält, die nicht definiert Alternate.mastersind. Der Markupteil dieser beiden Seiten verfügt über eine @MasterType Direktive, die auf die Site.master Gestaltungsvorlage verweist.

<%@ MasterType VirtualPath="~/Site.master" %>

Außerdem enthält der Ereignishandler ~/Admin/AddProduct.aspx von ItemInserted DetailsView Code, der die lose typierte Eigenschaft in ein Objekt vom Typ SitewandeltPage.Master. Die @MasterType Direktive (auf diese Weise verwendet) und die Umwandlung im ItemInserted Ereignishandler werden eng mit ~/Admin/AddProduct.aspx ~/Admin/Products.aspx der Site.master Gestaltungsvorlage gekoppelt.

Um diese enge Kopplung zu unterbrechen, können wir von einer gemeinsamen Basisklasse abgeleitet werden Site.master Alternate.master , die Definitionen für die öffentlichen Member enthält. Anschließend können wir die @MasterType Direktive aktualisieren, um auf diesen gemeinsamen Basistyp zu verweisen.

Erstellen einer benutzerdefinierten Basisgestaltungsvorlagenklasse

Fügen Sie dem App_Code Ordner namens BaseMasterPage.cs eine neue Klassendatei hinzu und leiten Sie sie von System.Web.UI.MasterPage. Wir müssen die RefreshRecentProductsGrid Methode und die GridMessageText Eigenschaft definieren BaseMasterPage, aber wir können sie nicht einfach dorthin Site.master verschieben, da diese Member mit Websteuerelementen arbeiten, die spezifisch für die Site.master Gestaltungsvorlage (GridView RecentProducts und GridMessage Label) sind.

Was wir tun müssen, ist so zu konfigurieren BaseMasterPage , dass diese Member dort definiert sind, aber tatsächlich von BaseMasterPageden abgeleiteten Klassen (Site.master und Alternate.master). Diese Art der Vererbung ist möglich, indem die Klasse und ihre Member als abstractmarkiert werden. Kurz gesagt: Durch das Hinzufügen des abstract Schlüsselworts zu diesen beiden Membern wird angekündigt, dass BaseMasterPage es nicht implementiert RefreshRecentProductsGrid wurde und GridMessageTextdass die abgeleiteten Klassen jedoch ausgeführt werden.

Darüber hinaus müssen wir das PricesDoubled Ereignis BaseMasterPage definieren und eine Möglichkeit durch die abgeleiteten Klassen zum Auslösen des Ereignisses bereitstellen. Das Muster, das in .NET Framework verwendet wird, um dieses Verhalten zu vereinfachen, besteht darin, ein öffentliches Ereignis in der Basisklasse zu erstellen und eine geschützte Methode virtual namens OnEventNamehinzuzufügen. Abgeleitete Klassen können diese Methode dann aufrufen, um das Ereignis auszulösen oder ihn außer Kraft zu setzen, 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:

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 zur Site.master CodeBehind-Klasse, und leiten Sie sie von BaseMasterPage. abstract Da BaseMasterPage wir diese abstract Mitglieder hier Site.masteraußer Kraft setzen müssen. Fügen Sie das override Schlüsselwort zu den Methoden- und Eigenschaftendefinitionen 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:

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 wir die CodeBehind-Klasse aktualisieren Alternate.master, um von BaseMasterPage den beiden abstract Membern abzuleiten und außer Kraft zu setzen. Da Alternate.master jedoch keine GridView enthält, die die neuesten Produkte oder eine Bezeichnung auflistet, die eine Meldung anzeigt, nachdem ein neues Produkt der 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 Basisgestaltungsvorlagenklasse

Nachdem wir die BaseMasterPage Klasse abgeschlossen haben und unsere beiden Gestaltungsvorlagen erweitert haben, besteht der letzte Schritt darin, die ~/Admin/AddProduct.aspx Seiten ~/Admin/Products.aspx zu aktualisieren, um auf diesen gemeinsamen Typ zu verweisen. Ändern Sie zunächst die @MasterType Direktive auf beiden Seiten von:

<%@ MasterType VirtualPath="~/Site.master" %>

In:

<%@ MasterType TypeName="BaseMasterPage" %>

Anstatt auf einen Dateipfad zu verweisen, verweist die @MasterType Eigenschaft jetzt auf den Basistyp (BaseMasterPage). Folglich ist die stark typierte Master Eigenschaft, die in den CodeBehind-Klassen beider Seiten verwendet wird, nun vom Typ BaseMasterPage (anstelle des Typs Site). Mit dieser Änderung an Ort reviditit ~/Admin/Products.aspx. Zuvor führte dies zu einem Umwandlungsfehler, da die Seite für die Verwendung der Alternate.master Gestaltungsvorlage konfiguriert ist, die @MasterType Direktive jedoch auf die Site.master Datei verweist. Jetzt wird die Seite jedoch ohne Fehler gerendert. Dies liegt daran, dass die Alternate.master Gestaltungsvorlage in ein Objekt des Typs BaseMasterPage umwandeln kann (da sie erweitert wird).

Es gibt eine kleine Änderung, die vorgenommen ~/Admin/AddProduct.aspxwerden muss. Der Ereignishandler des DetailsView-Steuerelements ItemInserted verwendet sowohl die stark typierte Master Eigenschaft als auch die lose typierte Page.Master Eigenschaft. Wir haben den stark typierten Verweis beim Aktualisieren der @MasterType Direktive behoben, aber wir müssen den lose typierten Verweis aktualisieren. Ersetzen Sie die folgende Codezeile:

Site myMasterPage = Page.Master as Site;

Mit der folgenden Umwandlung Page.Master in den Basistyp:

BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;

Schritt 4: Bestimmen, welche Gestaltungsvorlage an die Inhaltsseiten gebunden werden soll

Unsere BasePage Klasse legt derzeit alle Eigenschaften von Inhaltsseiten MasterPageFile auf einen hartcodierten Wert in der PreInit-Phase des Seitenlebenszyklus fest. Wir können diesen Code aktualisieren, um die Gestaltungsvorlage auf einem externen Faktor zu basieren. Möglicherweise hängt die zu ladende Gestaltungsvorlage von den Einstellungen des aktuell angemeldeten Benutzers ab. In diesem Fall müssen wir Code in der Methode schreiben, in BasePage der OnPreInit die Derzeit besuchten Gestaltungsvorlageneinstellungen des Benutzers nachschlagen.

Erstellen wir nun eine Webseite, die es dem Benutzer ermöglicht, auszuwählen, welche Gestaltungsvorlage verwendet werden soll – Site.master oder Alternate.master - und diese Auswahl in einer Sitzungsvariable zu speichern. Erstellen Sie zunächst eine neue Webseite im Stammverzeichnis namens ChooseMasterPage.aspx. Beim Erstellen dieser Seite (oder anderer Inhaltsseiten) müssen Sie sie nicht an eine Gestaltungsvorlage binden, da die Gestaltungsvorlage programmgesteuert BasePagefestgelegt ist. Wenn Sie die neue Seite jedoch nicht an eine Gestaltungsvorlage binden, enthält das standardmäßige deklarative Markup der neuen Seite ein Webformular und andere Inhalte, die von der Gestaltungsvorlage 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 Gestaltungsvorlage zu binden.

Hinweis

Da Site.master und Alternate.master über dieselbe Gruppe von ContentPlaceHolder-Steuerelementen verfügt, spielt es keine Rolle, welche Gestaltungsvorlage Sie beim Erstellen der neuen Inhaltsseite auswählen. Aus Gründen der Konsistenz würde ich die Verwendung Site.mastervorschlagen.

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

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

Bevor Sie der Seite Inhalte ChooseMasterPage.aspx hinzufügen, dauert es einen Moment, um die CodeBehind-Klasse der Seite zu aktualisieren, sodass sie von BasePage (anstelle von System.Web.UI.Page) abgeleitet wird. Fügen Sie als Nächstes der Seite ein DropDownList-Steuerelement hinzu, legen Sie dessen ID Eigenschaft fest MasterPageChoice, und fügen Sie zwei ListItems mit den Text Werten "~/Site.master" und "~/Alternate.master" hinzu.

Fügen Sie der Seite ein Schaltflächenwebsteuerelement hinzu, und legen Sie deren ID Eigenschaften Text bzw. Eigenschaften auf SaveLayout "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 Gestaltungsvorlagenauswahl 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 auf der ersten Seite ausgeführt (und nicht bei nachfolgenden Postbacks). Zunächst wird überprüft, ob die Sitzungsvariable MyMasterPage vorhanden ist. Wenn dies der Fall ist, wird versucht, das entsprechende ListItem in der MasterPageChoice DropDownList zu finden. Wenn ein übereinstimmende ListItem gefunden wird, wird seine Selected Eigenschaft auf true.

Außerdem benötigen wir Code, der die Auswahl des Benutzers in der MyMasterPage Sitzungsvariable speichert. Erstellen Sie einen Ereignishandler für das Ereignis der SaveLayout Schaltfläche 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

Wenn der Click Ereignishandler nach dem Postback ausgeführt wird, wurde die Gestaltungsvorlage bereits ausgewählt. Daher wird die Dropdownlistenauswahl des Benutzers erst wirksam, wenn die nächste Seite besucht wird. Der Response.Redirect Browser wird gezwungen, die Anforderung erneut anzufordern ChooseMasterPage.aspx.

Nachdem die ChooseMasterPage.aspx Seite abgeschlossen ist, besteht die letzte Aufgabe darin, die MasterPageFile Eigenschaft basierend auf dem Wert der MyMasterPage Sitzungsvariablen zuzuweisenBasePage. Wenn die Session-Variable nicht festgelegt ist, ist BasePage standardmäßig 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 verschoben, der die Eigenschaft des Page MasterPageFile Objekts aus dem OnPreInit Ereignishandler und in zwei separate Methoden zuweist. Diese erste Methode , weist die MasterPageFile Eigenschaft dem Wert zu, SetMasterPageFileder von der zweiten Methode zurückgegeben wird. GetMasterPageFileFromSession Ich habe die SetMasterPageFile Methode virtual so erstellt, dass zukünftige Klassen, die erweitert BasePage werden, optional außer Kraft setzen können, um benutzerdefinierte Logik zu implementieren, falls erforderlich. Im nächsten Lernprogramm wird ein Beispiel für die Außerkraftsetzung BasePageder SetMasterPageFile Eigenschaft angezeigt.

Rufen Sie mit diesem Code die ChooseMasterPage.aspx Seite auf. Zunächst ist die Site.master Gestaltungsvorlage ausgewählt (siehe Abbildung 6), aber der Benutzer kann eine andere Gestaltungsvorlage aus der Dropdownliste auswählen.

Inhaltsseiten werden mithilfe der Gestaltungsvorlage

Abbildung 06: Inhaltsseiten werden mithilfe der Gestaltungsvorlage angezeigt (Zum Anzeigen des Site.master Bilds mit voller Größe klicken)

Inhaltsseiten werden jetzt mithilfe der Gestaltungsvorlage

Abbildung 07: Inhaltsseiten werden jetzt mithilfe der Gestaltungsvorlage angezeigt (Zum Anzeigen des Alternate.master Bilds mit voller Größe klicken)

Zusammenfassung

Wenn eine Inhaltsseite besucht wird, werden die Inhaltssteuerelemente mit den ContentPlaceHolder-Steuerelementen der Gestaltungsvorlage verschmolzen. Die Gestaltungsvorlage der Inhaltsseite wird durch die Eigenschaft der Page Klasse MasterPageFile gekennzeichnet, die dem Attribut der @Page Direktive MasterPageFile während der Initialisierungsphase zugewiesen wird. Wie in diesem Lernprogramm gezeigt, können wir der MasterPageFile Eigenschaft einen Wert zuweisen, solange wir dies vor dem Ende der PreInit-Phase tun. Durch die programmgesteuerte Angabe der Gestaltungsvorlage wird die Tür für erweiterte Szenarien geöffnet, z. B. die dynamische Bindung einer Inhaltsseite an eine Gestaltungsvorlage basierend auf externen Faktoren.

Glückliche Programmierung!

Weitere nützliche Informationen

Weitere Informationen zu den in diesem Lernprogramm 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 Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 3.5 in 24 Stunden. Scott kann über seinen Blog unter mitchell@4GuysFromRolla.com oder über seinen Blog erreicht http://ScottOnWriting.NETwerden.

Besonderer Dank an

Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Lernprogramm war Suchi Banerjee. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn dies der Fall ist, legen Sie mir eine Zeile bei mitchell@4GuysFromRolla.com