Pagine master annidate (C#)

di Scott Mitchell

Mostra come annidare una pagina master all'interno di un'altra.

Introduzione

Nel corso delle ultime nove esercitazioni abbiamo visto come implementare un layout a livello di sito con pagine master. In una breve sintesi, le pagine master consentono allo sviluppatore di pagine di definire il markup comune nella pagina master insieme a aree specifiche che possono essere personalizzate in base a una pagina di contenuto per contenuto. I controlli ContentPlaceHolder in una pagina master indicano le aree personalizzabili; il markup personalizzato per i controlli ContentPlaceHolder viene definito nella pagina del contenuto tramite i controlli Contenuto.

Le tecniche della pagina master esaminate finora sono ideali se si dispone di un unico layout usato nell'intero sito. Tuttavia, molti siti Web di grandi dimensioni hanno un layout del sito personalizzato in varie sezioni. Si consideri, ad esempio, un'applicazione di assistenza sanitaria usata dal personale ospedaliero per gestire le informazioni, le attività e la fatturazione dei pazienti. In questa applicazione possono essere presenti tre tipi di pagine Web:

  • Pagine specifiche del personale in cui i membri del personale possono aggiornare la disponibilità, visualizzare le pianificazioni o richiedere il tempo di vacanza.
  • Pagine specifiche del paziente in cui i membri del personale visualizzano o modificano le informazioni per un paziente specifico.
  • Pagine specifiche della fatturazione in cui i contabili esaminano lo stato delle attestazioni correnti e i report finanziari.

Ogni pagina può condividere un layout comune, ad esempio un menu nella parte superiore e una serie di collegamenti usati di frequente lungo la parte inferiore. Tuttavia, le pagine specifiche del personale, del paziente e della fatturazione potrebbero dover personalizzare questo layout generico. Ad esempio, tutte le pagine specifiche del personale devono includere un calendario e un elenco di attività che mostra la disponibilità e la pianificazione giornaliera dell'utente attualmente connessi. Forse tutte le pagine specifiche del paziente devono mostrare il nome, l'indirizzo e le informazioni assicurative per il paziente le cui informazioni vengono modificate.

È possibile creare tali layout personalizzati usando pagine master annidate. Per implementare lo scenario precedente, si inizierà creando una pagina master che ha definito il layout a livello di sito, il contenuto del menu e del piè di pagina, con ContentPlaceHolder che definisce le aree personalizzabili. Si creerebbe quindi tre pagine master annidate, una per ogni tipo di pagina Web. Ogni pagina master annidata definisce il contenuto tra il tipo di pagine di contenuto che usano la pagina master. In altre parole, la pagina master annidata per le pagine di contenuto specifiche del paziente includerebbe il markup e la logica programmatica per visualizzare informazioni sulla modifica del paziente. Quando si crea una nuova pagina specifica del paziente, la si associa a questa pagina master annidata.

Questa esercitazione inizia evidenziando i vantaggi delle pagine master annidate. Viene quindi illustrato come creare e usare pagine master annidate.

Nota

Le pagine master annidate sono state possibili dalla versione 2.0 di .NET Framework. Tuttavia, Visual Studio 2005 non includeva il supporto in fase di progettazione per le pagine master annidate. La buona notizia è che Visual Studio 2008 offre un'esperienza di progettazione avanzata per le pagine master annidate. Se si è interessati a usare pagine master annidate, ma si usa ancora Visual Studio 2005, vedere la voce di blog di Scott Guthrie, Suggerimenti per pagine master annidate in VS 2005 Design-Time.

Vantaggi delle pagine master annidate

Molti siti Web dispongono di una progettazione del sito oltre a progetti più personalizzati specifici per determinati tipi di pagine. Ad esempio, nell'applicazione Web demo è stata creata una sezione amministrazione rudimentaria (le pagine nella ~/Admin cartella). Attualmente le pagine Web nella ~/Admin cartella usano la stessa pagina master di quelle pagine non nella sezione amministrazione (ovvero, o Alternate.master, Site.master a seconda della selezione dell'utente).

Nota

Per ora, finge che il nostro sito abbia una sola pagina master, Site.master. Verrà usata la pagina master annidata con due pagine master (o più) a partire da "Uso di una pagina master annidata per la sezione amministrazione" più avanti in questa esercitazione.

Si supponga di aver chiesto di personalizzare il layout delle pagine di amministrazione per includere informazioni o collegamenti aggiuntivi che altrimenti non sarebbero presenti in altre pagine nel sito. Esistono quattro tecniche per implementare questo requisito:

  1. Aggiungere manualmente le informazioni specifiche dell'amministrazione e i collegamenti a ogni pagina del contenuto nella ~/Admin cartella.
  2. Aggiornare la Site.master pagina master per includere le informazioni e i collegamenti specifici della sezione Amministrazione e quindi aggiungere codice alla pagina master per visualizzare o nascondere queste sezioni in base al fatto che una delle pagine di amministrazione venga visitata.
  3. Creare una nuova pagina master specificamente per la sezione Amministrazione, copiare il markup da Site.master, aggiungere le informazioni e i collegamenti specifici della sezione Amministrazione e quindi aggiornare le pagine del contenuto nella ~/Admin cartella per usare questa nuova pagina master.
  4. Creare una pagina master annidata che si associa a Site.master e avere le pagine del contenuto nella ~/Admin cartella usano questa nuova pagina master annidata. Questa pagina master annidata include solo le informazioni aggiuntive e i collegamenti specifici delle pagine di amministrazione e non sarebbe necessario ripetere il markup già definito in Site.master.

La prima opzione è la meno appetibile. L'intero punto di uso delle pagine master consiste nel passare dalla necessità di copiare manualmente e incollare il markup comune alle nuove pagine di ASP.NET. La seconda opzione è accettabile, ma rende l'applicazione meno gestibile perché in blocco le pagine master con markup visualizzato solo occasionalmente e richiede agli sviluppatori di modificare la pagina master per aggirare questo markup e dover ricordare quando, esattamente, il markup viene visualizzato rispetto al momento in cui è nascosto. Questo approccio sarebbe meno tenibile come personalizzazioni da più e più tipi di pagine Web necessarie per essere accodati da questa singola pagina master.

La terza opzione rimuove il clutter e la complessità causa il problema della superficie con la seconda opzione. Tuttavia, l'opzione tre degli svantaggi principali è che richiede di copiare e incollare il layout comune dalla Site.master nuova pagina master specifica della sezione Amministrazione. Se in seguito si decide di modificare il layout a livello di sito, è necessario ricordare di modificarlo in due posizioni.

La quarta opzione, le pagine master annidate, offrono il meglio delle seconde e terze opzioni. Le informazioni sul layout a livello di sito vengono mantenute in un file, ovvero la pagina master di primo livello, mentre il contenuto specifico per le aree specifiche è separato in file diversi.

Questa esercitazione inizia con un'occhiata alla creazione e all'uso di una semplice pagina master annidata. Viene creata una nuova pagina master di primo livello, due pagine master annidate e due pagine di contenuto. A partire da "Uso di una pagina master annidata per la sezione Amministrazione", si esamina l'aggiornamento dell'architettura della pagina master esistente per includere l'uso delle pagine master annidate. In particolare, viene creata una pagina master annidata e usata per includere contenuto personalizzato aggiuntivo per le pagine del contenuto nella ~/Admin cartella.

Passaggio 1: Creazione di una pagina master di Top-Level semplice

La creazione di un master annidato in base a una delle pagine master esistenti e quindi l'aggiornamento di una pagina di contenuto esistente per usare questa nuova pagina master annidata anziché la pagina master di primo livello comporta una certa complessità perché le pagine di contenuto esistenti prevedono già determinati controlli ContentPlaceHolder definiti nella pagina master di primo livello. Pertanto, la pagina master annidata deve includere anche gli stessi controlli ContentPlaceHolder con gli stessi nomi. Inoltre, l'applicazione demo specifica include due pagine master (Site.master e Alternate.master) assegnate dinamicamente a una pagina del contenuto in base alle preferenze di un utente, che aggiunge ulteriormente questa complessità. Verrà esaminato l'aggiornamento dell'applicazione esistente per l'uso di pagine master annidate più avanti in questa esercitazione, ma si esaminerà prima di tutto un semplice esempio di pagine master annidate.

Creare una nuova cartella denominata NestedMasterPages e quindi aggiungere un nuovo file di pagina master a tale cartella denominata Simple.master. Vedere la figura 1 per una schermata del Esplora soluzioni dopo l'aggiunta di questa cartella e del file. Trascinare il file del foglio di stile dall'Esplora soluzioni AlternateStyles.css nella Designer. Questo aggiunge un <link> elemento al file del foglio di stile nell'elemento <head> , dopo il quale il markup dell'elemento della <head> pagina master dovrebbe essere simile al seguente:

<head runat="server">
 <title>Untitled Page</title> 
 <asp:ContentPlaceHolder id="head" runat="server"> 
 </asp:ContentPlaceHolder>
 <link href="../AlternateStyles.css" rel="stylesheet" type="text/css" /> 
</head>

Aggiungere quindi il markup seguente all'interno del Modulo Web di Simple.master:

<div id="topContent"> 
 <asp:HyperLink ID="lnkHome" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx"
 Text="Nested Master Pages Tutorial (Simple)" /> 
</div> 
<div id="mainContent"> 
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
</div>

Questo markup visualizza un collegamento denominato "Pagine master nidificate (Semplice)" nella parte superiore della pagina in un carattere bianco di grandi dimensioni su sfondo marina. Sotto che è MainContent ContentPlaceHolder. La figura 1 mostra la Simple.master pagina master quando viene caricata nella Designer di Visual Studio.

Pagina master punto semplice quando viene caricata nella Designer di Visual Studio.

Figura 01: la pagina master annidata definisce il contenuto specifico delle pagine nella sezione Amministrazione (fare clic per visualizzare l'immagine full-size)

Passaggio 2: Creazione di una pagina master annidata semplice

Simple.master contiene due controlli ContentPlaceHolder: MainContent ContentPlaceHolder aggiunti all'interno del Web Form insieme al head ContentPlaceHolder nell'elemento <head> . Se si vuole creare una pagina del contenuto e associarla alla pagina del contenuto, sono presenti due controlli Contenuto che fanno riferimento ai Simple.master due ContentPlaceHolder. Analogamente, se si crea una pagina master annidata e la si associa a Simple.master , la pagina master annidata avrà due controlli contenuto.

Aggiungere una nuova pagina master annidata alla NestedMasterPages cartella denominata SimpleNested.master. Fare clic con il pulsante destro del mouse sulla NestedMasterPages cartella e scegliere Aggiungi nuovo elemento. Viene visualizzata la finestra di dialogo Aggiungi nuovo elemento visualizzata nella figura 2. Selezionare il tipo di modello pagina master e digitare il nome della nuova pagina master. Per indicare che la nuova pagina master deve essere una pagina master annidata, selezionare la casella di controllo "Seleziona pagina master".

Fare quindi clic sul pulsante Aggiungi. Verrà visualizzata la stessa finestra di dialogo Seleziona pagina master visualizzata quando si associa una pagina del contenuto a una pagina master (vedere la figura 3). Scegliere la Simple.master pagina master nella NestedMasterPages cartella e fare clic su OK.

Nota

Se è stato creato il sito Web ASP.NET usando il modello di progetto applicazione Web anziché il modello progetto sito Web, non verrà visualizzata la casella di controllo "Seleziona pagina master" nella finestra di dialogo Aggiungi nuovo elemento visualizzata nella figura 2. Per creare una pagina master annidata quando si usa il modello di progetto applicazione Web, è necessario scegliere il modello pagina master annidata anziché il modello pagina master. Dopo aver selezionato il modello pagina master annidata e fare clic su Aggiungi, verrà visualizzata la stessa finestra di dialogo Seleziona pagina master visualizzata nella figura 3.

Selezionare la casella di controllo

Figura 02: selezionare la casella di controllo "Seleziona pagina master" per aggiungere una pagina master annidata (fare clic per visualizzare l'immagine a dimensioni complete)

Associare la pagina master annidata alla pagina Master Simple.master

Figura 03: Associare la pagina master annidata alla Simple.master pagina master (fare clic per visualizzare l'immagine a dimensioni complete)

Il markup dichiarativo della pagina master annidato, illustrato di seguito, contiene due controlli Contenuto che fanno riferimento ai due controlli della pagina master di primo livello.

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 </asp:Content>

Ad eccezione della <%@ Master %> direttiva, il markup dichiarativo iniziale della pagina master annidata è identico al markup generato inizialmente quando si associa una pagina del contenuto alla stessa pagina master di primo livello. Analogamente alla direttiva di <%@ Page %> una pagina del contenuto, la <%@ Master %> direttiva include un MasterPageFile attributo che specifica la pagina master padre della pagina master annidata. La differenza principale tra la pagina master annidata e una pagina del contenuto associata alla stessa pagina master di primo livello è che la pagina master annidata può includere i controlli ContentPlaceHolder. I controlli ContentPlaceHolder della pagina master annidata definiscono le aree in cui le pagine di contenuto possono personalizzare il markup.

Aggiornare questa pagina master annidata in modo che visualizzi il testo "Hello, from SimpleNested!" nel controllo Contenuto corrispondente al MainContent controllo ContentPlaceHolder.

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
</asp:Content>

Dopo aver effettuato questa aggiunta, salvare la pagina master nidificata e quindi aggiungere una nuova pagina di contenuto alla NestedMasterPages cartella denominata Default.aspxe associarla alla SimpleNested.master pagina master. Dopo aver aggiunto questa pagina, potresti essere sorpreso di vedere che non contiene controlli Contenuto (vedere la figura 4)! Una pagina di contenuto può accedere solo ai ContentPlaceHolders della pagina master padre . SimpleNested.master non contiene controlli ContentPlaceHolder; pertanto, qualsiasi pagina di contenuto associata a questa pagina master non può contenere controlli Contenuto.

La nuova pagina contenuto non contiene controlli contenuto

Figura 04: La pagina Nuovo contenuto non contiene controlli contenuto (fare clic per visualizzare l'immagine a dimensione intera)

È necessario aggiornare la pagina master nidificata (SimpleNested.master) per includere i controlli ContentPlaceHolder. In genere, si desidera che le pagine master nidificate includano un ContentPlaceHolder per ogni ContentPlaceHolder definito dalla relativa pagina master padre, consentendo in tal modo la pagina master figlio o la pagina del contenuto di funzionare con uno dei controlli ContentPlaceHolder della pagina master di primo livello.

Aggiornare la SimpleNested.master pagina master in modo da includere un ContentPlaceHolder nei due controlli Contenuto. Assegnare ai controlli ContentPlaceHolder lo stesso nome del controllo ContentPlaceHolder a cui fa riferimento il controllo Contenuto. Ovvero, aggiungere un controllo ContentPlaceHolder denominato MainContent al controllo Contenuto in SimpleNested.master che fa riferimento a MainContent ContentPlaceHolder in Simple.master. Eseguire la stessa operazione nel controllo Contenuto che fa riferimento a head ContentPlaceHolder.

Nota

Anche se è consigliabile assegnare un nome ai controlli ContentPlaceHolder nella pagina master nidificata come ContentPlaceHolders nella pagina master di primo livello, questa simmetria di denominazione non è necessaria. È possibile assegnare ai controlli ContentPlaceHolder nella pagina master nidificata qualsiasi nome desiderato. Tuttavia, trovo più facile ricordare ciò che ContentPlaceHolders corrisponde alle aree della pagina se la pagina master di primo livello e le pagine master nidificate usano gli stessi nomi.

Dopo aver apportato queste aggiunte, il SimpleNested.master markup dichiarativo della pagina master dovrebbe essere simile al seguente:

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master"AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

Eliminare la pagina di Default.aspx contenuto appena creata e quindi aggiungerla nuovamente, associandola alla SimpleNested.master pagina master. Questa volta Visual Studio aggiunge due controlli Contenuto a , facendo riferimento a Default.aspxContentPlaceHolders ora definiti in SimpleNested.master (vedere la figura 6). Aggiungere il testo "Hello, from Default.aspx!" nel controllo Contenuto a cui si fa MainContentriferimento .

La figura 5 mostra le tre entità coinvolte in questo caso: Simple.master, SimpleNested.mastere Default.aspx e come sono correlate l'una all'altra. Come illustrato nel diagramma, la pagina master nidificata implementa i controlli Contenuto per contentPlaceHolder dell'elemento padre. Se queste aree devono essere accessibili alla pagina del contenuto, la pagina master nidificata deve aggiungere i propri ContentPlaceHolders ai controlli Contenuto.

Le pagine master Top-Level e annidate determinano il layout della pagina contenuto

Figura 05: Le pagine master Top-Level e annidate determinano il layout della pagina contenuto (fare clic per visualizzare l'immagine a dimensione intera)

Questo comportamento illustra come una pagina di contenuto o una pagina master sia riconosciuta solo dalla relativa pagina master padre. Questo comportamento è indicato anche dal Designer di Visual Studio. La figura 6 mostra il Designer per Default.aspx. Anche se il Designer mostra chiaramente quali aree sono modificabili dalla pagina del contenuto e quali parti non sono, non ambiguità per quali aree non modificabili provengono dalla pagina master nidificata e quali aree provengono dalla pagina master di primo livello.

La pagina Contenuto include ora controlli contenuto per i contentPlaceHolders della pagina master annidata

Figura 06: La pagina contenuto include ora controlli contenuto per i contentplaceholder della pagina master annidata (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Aggiunta di una seconda pagina master annidata semplice

Il vantaggio delle pagine master nidificate è più evidente quando sono presenti più pagine master annidate. Per illustrare questo vantaggio, creare un'altra pagina master nidificata nella NestedMasterPages cartella, denominare la nuova pagina SimpleNestedAlternate.master master nidificata e associarla alla Simple.master pagina master. Aggiungere controlli ContentPlaceHolder nei due controlli Contenuto annidati della pagina master come nel passaggio 2. Aggiungere anche il testo "Hello, from SimpleNestedAlternate!" nel controllo Contenuto che corrisponde al ContentPlaceHolder della pagina master di MainContent primo livello. Dopo aver apportato queste modifiche, il markup dichiarativo della nuova pagina master annidata dovrebbe essere simile al seguente:

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNestedAlternate.master.cs" Inherits="NestedMasterPages_SimpleNestedAlternate" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
 <asp:ContentPlaceHolder ID="head" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 <p>Hello, from SimpleNestedAlternate!</p> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content>

Creare una pagina di contenuto denominata Alternate.aspx nella NestedMasterPages cartella e associarla alla SimpleNestedAlternate.master pagina master nidificata. Aggiungere il testo "Hello, from Alternate!" nel controllo Contenuto che corrisponde a MainContent. La figura 7 mostra Alternate.aspx quando viene visualizzata tramite il Designer di Visual Studio.

Alternate.aspx è associato alla pagina master SimpleNestedAlternate.master

Figura 07: Alternate.aspx è associato alla pagina master (fare clic per visualizzare l'immagineSimpleNestedAlternate.master a dimensione intera)

Confrontare il Designer nella figura 7 con il Designer nella figura 6. Entrambe le pagine di contenuto condividono lo stesso layout definito nella pagina master di primo livello (Simple.master), ovvero il titolo "Nested Master Pages Tutorial (Simple)". Entrambi hanno tuttavia contenuto distinto definito nelle pagine master padre: il testo "Hello, from SimpleNested!" nella figura 6 e "Hello, from SimpleNestedAlternate!" nella figura 7. A questo punto, queste differenze sono semplici, ma è possibile estendere questo esempio in modo da includere differenze più significative. Ad esempio, la SimpleNested.master pagina potrebbe includere un menu con opzioni specifiche per le pagine di contenuto, mentre SimpleNestedAlternate.master potrebbero avere informazioni pertinenti alle pagine di contenuto associate.

Si supponga ora di dover apportare una modifica al layout del sito globale. Si supponga, ad esempio, di voler aggiungere un elenco di collegamenti comuni a tutte le pagine di contenuto. A tale scopo, si aggiorna la pagina master di primo livello, Simple.master. Tutte le modifiche apportate vengono immediatamente riflesse nelle pagine master nidificate e, per estensione, nelle pagine di contenuto.

Per illustrare la facilità con cui è possibile modificare il layout del sito in generale, aprire la Simple.master pagina master e aggiungere il markup seguente tra gli topContent elementi e mainContent<div> :

<div id="navContent"> 
 <asp:HyperLink ID="lnkDefault" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx" 
 Text="Nested Master Page Example 1" /> 
 | 
 <asp:HyperLink ID="lnkAlternate" runat="server" 
 NavigateUrl="~/NestedMasterPages/Alternate.aspx" 
 Text="Nested Master Page Example 2" /> 
</div>

In questo modo vengono aggiunti due collegamenti alla parte superiore di ogni pagina associata a Simple.master, SimpleNested.mastero SimpleNestedAlternate.master. Queste modifiche si applicano immediatamente a tutte le pagine master nidificate e alle relative pagine di contenuto. La figura 8 mostra Alternate.aspx quando viene visualizzata tramite un browser. Si noti l'aggiunta dei collegamenti nella parte superiore della pagina (rispetto alla figura 7).

Le modifiche apportate alla pagina master Top-Level vengono immediatamente riflesse nelle pagine master annidate e nelle relative pagine di contenuto

Figura 08: Le modifiche apportate alla pagina master Top-Level vengono immediatamente riflesse nelle pagine master annidate e nelle relative pagine di contenuto (fare clic per visualizzare l'immagine a dimensione intera)

Uso di una pagina master nidificata per la sezione Amministrazione

A questo punto sono stati esaminati i vantaggi delle pagine master annidate e si è visto come crearli e usarli in un'applicazione ASP.NET. Gli esempi descritti in Passaggi 1, 2 e 3, tuttavia, implicavano la creazione di una nuova pagina master di primo livello, nuove pagine master nidificate e nuove pagine di contenuto. Che ne dici di aggiungere una nuova pagina master annidata a un sito Web con una pagina master e pagine di contenuto di primo livello esistenti?

L'integrazione di una pagina master nidificata in un sito Web esistente e l'associazione con le pagine di contenuto esistenti richiede un po' più impegno rispetto all'avvio da zero. I passaggi 4, 5, 6 e 7 esplorano queste sfide man mano che si aumenta l'applicazione demo per includere una nuova pagina master annidata denominata AdminNested.master che contiene istruzioni per l'amministratore e viene usata dalle pagine ASP.NET nella ~/Admin cartella.

L'integrazione di una pagina master nidificata nell'applicazione demo introduce i seguenti ostacoli:

  • Le pagine di contenuto esistenti nella ~/Admin cartella hanno determinate aspettative rispetto alla pagina master. Per iniziare, si prevede che siano presenti determinati controlli ContentPlaceHolder. Inoltre, le ~/Admin/AddProduct.aspx pagine e ~/Admin/Products.aspx chiamano il metodo pubblico RefreshRecentProductsGrid della pagina master, impostano la relativa GridMessageText proprietà o hanno un gestore eventi per il relativo PricesDoubled evento. Di conseguenza, la pagina master nidificata deve fornire gli stessi ContentPlaceHolders e i membri pubblici.
  • Nell'esercitazione precedente è stata migliorata la BasePage classe per impostare dinamicamente la Page proprietà dell'oggetto MasterPageFile in base a una variabile Session. Come è possibile supportare le pagine master dinamiche quando si usano pagine master nidificate?

Queste due sfide verranno affrontate man mano che si crea la pagina master annidata e la si userà dalle pagine di contenuto esistenti. Questi problemi verranno esaminati e smontabili man mano che si verificano.

Passaggio 4: Creazione della pagina master annidata

La prima attività consiste nel creare la pagina master nidificata da usare nelle pagine della sezione Amministrazione. Come illustrato nel passaggio 2, quando si aggiunge una nuova pagina master nidificata è necessario specificare la pagina master padre della pagina master annidata. Sono tuttavia disponibili due pagine master di primo livello: Site.master e Alternate.master. Tenere presente che è stato creato Alternate.master nell'esercitazione precedente e scritto codice nella BasePage classe che imposta la proprietà dell'oggetto Page in fase di MasterPageFile esecuzione su Site.master o Alternate.master a seconda del valore della MyMasterPage variabile Session.

Come si configura la pagina master nidificata in modo che usi la pagina master di primo livello appropriata? Sono disponibili due opzioni:

  • Creare due pagine AdminNestedSite.master master nidificate e AdminNestedAlternate.mastere associarle rispettivamente alle pagine Site.master master di primo livello e Alternate.master. In BasePage, quindi, si imposta l'oggetto PageMasterPageFile sulla pagina master annidata appropriata.
  • Creare una singola pagina master nidificata e fare in modo che le pagine di contenuto usino questa pagina master specifica. In fase di esecuzione è quindi necessario impostare la proprietà della MasterPageFile pagina master nidificata sulla pagina master di primo livello appropriata in fase di esecuzione. (Come si potrebbe aver capito da ora, anche le pagine master hanno una MasterPageFile proprietà.

Si userà la seconda opzione. Creare un singolo file di pagina master annidato nella ~/Admin cartella denominata AdminNested.master. Poiché entrambi Site.master e Alternate.master hanno lo stesso set di controlli ContentPlaceHolder, non importa a quale pagina master lo associ, anche se ti invito a associarlo a Site.master per motivi di coerenza.

Aggiungere una pagina master annidata alla cartella ~/Amministrazione.

Figura 09: Aggiungere una pagina master annidata alla ~/Admin cartella. (Fare clic per visualizzare l'immagine a dimensione intera)

Poiché la pagina master nidificata è associata a una pagina master con quattro controlli ContentPlaceHolder, Visual Studio aggiunge quattro controlli Contenuto al markup iniziale del nuovo file di pagina master annidato. Come nei passaggi 2 e 3, aggiungere un controllo ContentPlaceHolder in ogni controllo Contenuto, assegnandogli lo stesso nome del controllo ContentPlaceHolder della pagina master di primo livello. Aggiungere anche il markup seguente al controllo Contenuto che corrisponde al MainContent ContentPlaceHolder:

<div class="instructions"> 
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
</div>

Definire quindi la instructions classe CSS nei Styles.css file CSS e AlternateStyles.css . Le regole CSS seguenti causano la visualizzazione degli elementi HTML con la instructions classe con un colore di sfondo giallo chiaro e un bordo nero a tinta unita:

.instructions 
{ 
 padding: 6px; 
 border: dashed 1px black; 
 background-color: #ffb; 
 margin-bottom: 10px; 
}

Poiché questo markup è stato aggiunto alla pagina master nidificata, verrà visualizzato solo in tali pagine che usano questa pagina master nidificata ,vale a dire le pagine della sezione Amministrazione.

Dopo aver apportato queste aggiunte alla pagina master annidata, il markup dichiarativo dovrebbe essere simile al seguente:

<%@ Master Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="AdminNested.master.cs" Inherits="Admin_AdminNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <div class="instructions">
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
 </div> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content3" ContentPlaceHolderID="QuickLoginUI" Runat="Server"> 
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content4" ContentPlaceHolderID="LeftColumnContent" Runat="Server"> 
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

Si noti che a ogni controllo Content è associato un controllo ContentPlaceHolder e che alle proprietà dei controlli ContentPlaceHolder vengono ID assegnati gli stessi valori dei controlli ContentPlaceHolder corrispondenti nella pagina master di primo livello. Inoltre, il markup specifico della MainContent sezione Amministrazione viene visualizzato nel ContentPlaceHolder.

La figura 10 mostra la pagina master annidata quando visualizzata tramite la AdminNested.master Designer di Visual Studio. È possibile visualizzare le istruzioni nella casella gialla nella parte superiore del MainContent controllo Contenuto.

La pagina master annidata estende la pagina master Top-Level per includere istruzioni per l'amministratore.

Figura 10: la pagina master annidata estende la pagina master Top-Level per includere istruzioni per l'amministratore. (Fare clic per visualizzare l'immagine full-size)

Passaggio 5: Aggiornamento delle pagine di contenuto esistenti per usare la nuova pagina master annidata

Ogni volta che si aggiunge una nuova pagina di contenuto alla sezione Amministrazione, è necessario associarla alla AdminNested.master pagina master appena creata. Ma quali sono le pagine di contenuto esistenti? Attualmente tutte le pagine di contenuto nel sito derivano dalla BasePage classe, che imposta a livello di codice la pagina master della pagina del contenuto in fase di esecuzione. Non si tratta del comportamento desiderato per le pagine del contenuto nella sezione Amministrazione. Invece, si vuole che queste pagine di contenuto usino sempre la AdminNested.master pagina. Sarà responsabilità della pagina master annidata scegliere la pagina del contenuto di primo livello in fase di esecuzione.

Per ottenere il modo migliore per ottenere questo comportamento desiderato, è creare una nuova classe di pagina di base personalizzata denominata AdminBasePage che estende la BasePage classe. AdminBasePagepuò quindi eseguire l'override SetMasterPageFile dell'oggetto MasterPageFile e impostare Page il valore hardcoded "~/Amministrazione/AdminNested.master". In questo modo, qualsiasi pagina AdminBasePage derivata da userà AdminNested.master, mentre qualsiasi pagina che deriva da BasePage avrà la relativa MasterPageFile proprietà impostata dinamicamente su "~/Site.master" o "~/Alternate.master" in base al valore della MyMasterPage variabile Session.

Iniziare aggiungendo un nuovo file di classe alla App_Code cartella denominata AdminBasePage.cs. Eseguire AdminBasePage l'estensione BasePage e quindi eseguire l'override del SetMasterPageFile metodo. In tale metodo assegnare il MasterPageFile valore "~/Amministrazione/AdminNested.master". Dopo aver apportato queste modifiche, il file di classe dovrebbe essere simile al seguente:

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
    } 
}

È ora necessario disporre delle pagine di contenuto esistenti nella sezione Amministrazione derivare da AdminBasePage anziché BasePageda . Passare al file di classe code-behind per ogni pagina del contenuto nella ~/Admin cartella e apportare questa modifica. Ad esempio, in ~/Admin/Default.aspx si modifica la dichiarazione di classe code-behind da:

public partial class Admin_Default : BasePage

Con:

public partial class Admin_Default : AdminBasePage

La figura 11 illustra il modo in cui la pagina master di primo livello (o Alternate.master), la pagina master annidata (Site.masterAdminNested.master) e le pagine del contenuto della sezione Amministrazione si riferiscono tra loro.

La pagina master annidata definisce il contenuto specifico delle pagine nella sezione Amministrazione

Figura 11: la pagina master annidata definisce il contenuto specifico delle pagine nella sezione Amministrazione (fare clic per visualizzare l'immagine full-size)

Passaggio 6: Mirroring dei metodi e delle proprietà della pagina master

Si ricordi che le pagine e ~/Admin/Products.aspx interagiscono a livello di codice con la pagina master: ~/Admin/AddProduct.aspx chiama il metodo pubblico RefreshRecentProductsGrid della pagina master e imposta la relativa GridMessageText proprietà; ~/Admin/Products.aspx ha un gestore eventi per l'eventoPricesDoubled.~/Admin/AddProduct.aspx Nell'esercitazione precedente è stata creata una classe astratta BaseMasterPage che ha definito questi membri pubblici.

Le ~/Admin/AddProduct.aspx pagine e ~/Admin/Products.aspx presuppongono che la BaseMasterPage pagina master deriva dalla classe . La AdminNested.master pagina, tuttavia, estende attualmente la System.Web.UI.MasterPage classe. Di conseguenza, quando si visita ~/Admin/Products.aspx un InvalidCastException oggetto viene generato con il messaggio: "Impossibile eseguire il cast dell'oggetto di tipo 'ASP.admin_adminnested_master' per digitare "BaseMasterPage".

Per risolvere questo problema, è necessario disporre della AdminNested.master classe code-behind estendere BaseMasterPage. Aggiornare la dichiarazione della classe code-behind della pagina master annidata da:

public partial class Admin_AdminNested : System.Web.UI.MasterPage

Con:

public partial class Admin_AdminNested : BaseMasterPage

Non siamo ancora stati fatti. Poiché la classe è astratta, è necessario eseguire l'override BaseMasterPage dei abstract membri RefreshRecentProductsGrid e GridMessageText. Questi membri vengono usati dalle pagine master di primo livello per aggiornare le interfacce utente. In realtà, solo la Site.master pagina master usa questi metodi, anche se entrambe le pagine master di primo livello implementano questi metodi, poiché entrambi estendono BaseMasterPage.)

Anche se è necessario implementare questi membri in AdminNested.master, tutte queste implementazioni devono eseguire è semplicemente chiamare lo stesso membro nella pagina master di primo livello utilizzata dalla pagina master annidata. Ad esempio, quando una pagina di contenuto nella sezione Amministrazione chiama il metodo della RefreshRecentProductsGrid pagina master annidata, tutte le pagine master annidate devono eseguire è, a sua volta, il metodo chiama Site.master o Alternate.master's RefreshRecentProductsGrid .

Per ottenere questo risultato, iniziare aggiungendo la direttiva seguente @MasterType all'inizio di AdminNested.master:

<%@ MasterType TypeName="BaseMasterPage" %>

Tenere presente che la @MasterType direttiva aggiunge una proprietà fortemente tipizzata alla classe code-behind denominata Master. Eseguire quindi l'override dei RefreshRecentProductsGrid membri e GridMessageText e semplicemente delegare la chiamata al Mastermetodo corrispondente:

public partial class Admin_AdminNested : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        Master.RefreshRecentProductsGrid();
    } 
    public override string GridMessageText
    { 
        get 
        {
            return Master.GridMessageText;
        } 
        set
        { 
            Master.GridMessageText = value; 
        } 
    }
}

Con questo codice sul posto, è necessario visitare e usare le pagine del contenuto nella sezione Amministrazione. La figura 12 mostra la ~/Admin/Products.aspx pagina quando visualizzata tramite un browser. Come si può vedere, la pagina include la casella Istruzioni di amministrazione, definita nella pagina master annidata.

Le pagine contenuto nella sezione Amministrazione includono istruzioni nella parte superiore di ogni pagina

Figura 12: Le pagine contenuto nella sezione Amministrazione includono istruzioni nella parte superiore di ogni pagina (fare clic per visualizzare l'immagine full-size)

Passaggio 7: Uso della pagina master Top-Level appropriata in fase di esecuzione

Anche se tutte le pagine del contenuto nella sezione Amministrazione sono completamente funzionali, tutte usano la stessa pagina master di primo livello e ignorano la pagina master selezionata dall'utente in ChooseMasterPage.aspx. Questo comportamento è dovuto al fatto che la pagina master annidata ha la relativa MasterPageFile proprietà impostata staticamente su Site.master nella relativa <%@ Master %> direttiva.

Per usare la pagina master di primo livello selezionata dall'utente finale, è necessario impostare la AdminNested.masterproprietà 's MasterPageFile sul valore nella MyMasterPage variabile Sessione. Poiché vengono impostate le proprietà delle pagine MasterPageFile del contenuto in BasePage, è possibile che la proprietà BaseMasterPage della MasterPageFile pagina master annidata sia impostata nella AdminNested.masterclasse code-behind. Ciò non funzionerà, tuttavia, perché è necessario impostare la MasterPageFile proprietà entro la fine della fase PreInit. La prima volta che è possibile toccare a livello di codice il ciclo di vita della pagina da una pagina master è la fase Init (che si verifica dopo la fase PreInit).

Pertanto, è necessario impostare la proprietà della pagina master annidata dalle pagine del MasterPageFile contenuto. Le uniche pagine di contenuto che usano la AdminNested.master pagina master derivano da AdminBasePage. Pertanto, possiamo mettere questa logica lì. Nel passaggio 5 si esegue l'overrode del SetMasterPageFile metodo impostando la Page proprietà dell'oggetto MasterPageFile su "~/Amministrazione/AdminNested.master". Aggiornare SetMasterPageFile anche per impostare la proprietà della MasterPageFile pagina master sul risultato archiviato nella sessione:

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
        Page.Master.MasterPageFile = base.GetMasterPageFileFromSession(); 
    } 
}

Il GetMasterPageFileFromSession metodo, aggiunto alla BasePage classe nell'esercitazione precedente, restituisce il percorso del file di pagina master appropriato in base al valore della variabile Session.

Con questa modifica sul posto, la selezione della pagina master dell'utente passa alla sezione Amministrazione. La figura 13 mostra la stessa pagina della figura 12, ma dopo che l'utente ha modificato la selezione della pagina master in Alternate.master.

La pagina Amministrazione annidata usa la pagina master Top-Level selezionata dall'utente

Figura 13: la pagina Amministrazione annidata usa la pagina master Top-Level selezionata dall'utente (fare clic per visualizzare l'immagine a dimensioni complete)

Riepilogo

Analogamente alla modalità di associazione delle pagine del contenuto a una pagina master, è possibile creare pagine master annidate avendo una pagina master figlio associata a una pagina master padre. La pagina master figlio può definire i controlli Contenuto per ognuno dei contentPlaceHolder padre; può quindi aggiungere i propri controlli ContentPlaceHolder (nonché altri markup) a questi controlli Contenuto. Le pagine master annidate sono molto utili nelle applicazioni Web di grandi dimensioni in cui tutte le pagine condividono un aspetto e un aspetto sovraarchiviante, ma alcune sezioni del sito richiedono personalizzazioni univoche.

Programmazione felice!

Altre informazioni

Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:

Informazioni sull'autore

Scott Mitchell, autore di più libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 3,5 in 24 ore. Scott può essere raggiunto all'indirizzo mitchell@4GuysFromRolla.com o tramite il suo blog all'indirizzo http://ScottOnWriting.NET.

Grazie speciali

Questa serie di esercitazioni è stata esaminata da molti revisori utili. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com