Impostazione della pagina master a livello di codice (C#)

di Scott Mitchell

Esamina l'impostazione della pagina master della pagina del contenuto a livello di codice tramite il gestore eventi PreInit.

Introduzione

Poiché l'esempio inaugurale in Creazione di un layout Site-Wide usando pagine master, tutte le pagine del contenuto hanno fatto riferimento alla pagina master in modo dichiarativo tramite l'attributo MasterPageFile nella @Page direttiva. Ad esempio, la direttiva seguente @Page collega la pagina del contenuto alla pagina Site.mastermaster :

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

La Page classe nello System.Web.UI spazio dei nomi include una MasterPageFile proprietà che restituisce il percorso della pagina master della pagina del contenuto. Questa proprietà è impostata dalla @Page direttiva. Questa proprietà può essere usata anche per specificare a livello di codice la pagina master della pagina del contenuto. Questo approccio è utile se si vuole assegnare dinamicamente la pagina master in base a fattori esterni, ad esempio l'utente che visita la pagina.

In questa esercitazione viene aggiunta una seconda pagina master al sito Web e si decide in modo dinamico quale pagina master usare in fase di esecuzione.

Passaggio 1: Esaminare il ciclo di vita della pagina

Ogni volta che una richiesta arriva al server Web per una pagina ASP.NET che è una pagina del contenuto, il motore di ASP.NET deve unire i controlli Contenuto della pagina nei controlli ContentPlaceHolder corrispondenti della pagina master. Questa fusione crea una singola gerarchia di controllo che può quindi procedere attraverso il ciclo di vita della pagina tipico.

La figura 1 illustra questa fusione. Il passaggio 1 nella figura 1 mostra le gerarchie iniziali del controllo pagina e contenuto master. Alla fine della fase preInit i controlli Contenuto nella pagina vengono aggiunti ai contentPlaceHolder corrispondenti nella pagina master (Passaggio 2). Dopo questa fusione, la pagina master funge da radice della gerarchia di controllo fuso. Questa gerarchia di controllo fuso viene quindi aggiunta alla pagina per produrre la gerarchia di controllo finalizzata (passaggio 3). Il risultato netto è che la gerarchia di controllo della pagina include la gerarchia di controllo fuso.

Le gerarchie di controllo della pagina master e della pagina contenuto vengono unite durante la fase preinit

Figura 01: Le gerarchie di controllo della pagina master e della pagina contenuto vengono unite durante la fase preinit (fare clic per visualizzare l'immagine a dimensioni complete)

Passaggio 2: Impostazione dellaMasterPageFileproprietà dal codice

Ciò che fa parte della pagina master in questa fusione dipende dal valore della Page proprietà dell'oggetto MasterPageFile . MasterPageFile L'impostazione dell'attributo nella @Page direttiva ha l'effetto netto dell'assegnazione Pagedella proprietà 's MasterPageFile durante la fase di inizializzazione, ovvero la prima fase del ciclo di vita della pagina. In alternativa, è possibile impostare questa proprietà a livello di codice. Tuttavia, è imperativo che questa proprietà venga impostata prima della fusione nella figura 1.

All'inizio della fase PreInit l'oggetto genera PreInit l'eventoPage e chiama il OnPreInit relativo metodo. Per impostare la pagina master a livello di codice, è possibile creare un gestore eventi per l'evento o eseguire l'override del PreInitOnPreInit metodo. Di seguito vengono esaminati entrambi gli approcci.

Iniziare aprendo Default.aspx.cs, il file di classe code-behind per la home page del sito. Aggiungere un gestore eventi per l'evento della PreInit pagina digitando il codice seguente:

protected void Page_PreInit(object sender, EventArgs e) 
{ 
}

Da qui è possibile impostare la MasterPageFile proprietà. Aggiornare il codice in modo che assegna il valore "~/Site.master" alla MasterPageFile proprietà.

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

Se si imposta un punto di interruzione e si inizia con il debug, si noterà che ogni volta che la Default.aspx pagina viene visitata o ogni volta che è presente un postback in questa pagina, il Page_PreInit gestore eventi viene eseguito e la MasterPageFile proprietà viene assegnata a "~/Site.master".

In alternativa, è possibile eseguire l'override del Page metodo della OnPreInit classe e impostare la MasterPageFile proprietà. Per questo esempio, non è possibile impostare la pagina master in una determinata pagina, ma piuttosto da BasePage. Si ricordi che è stata creata una classe di pagina di base personalizzata (BasePage) nell'esercitazione Specificare il titolo, i meta tag e altre intestazioni HTML nell'esercitazione sulla pagina master . Attualmente BasePage esegue l'override Page del metodo della OnLoadComplete classe, in cui imposta la proprietà della Title pagina in base ai dati della mappa del sito. Si aggiornerà BasePage anche per eseguire l'override del OnPreInit metodo per specificare a livello di codice la pagina master.

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

Poiché tutte le pagine di contenuto derivano da BasePage, tutte le pagine hanno ora la relativa pagina master assegnata a livello di codice. A questo punto il PreInit gestore eventi in Default.aspx.cs è superfluo; è possibile rimuoverlo.

Che cos'è la@Pagedirettiva?

Ciò che può risultare un po' confuso è che le proprietà delle MasterPageFile pagine del contenuto vengono ora specificate in due posizioni: a livello di codice nel BasePage metodo della OnPreInit classe e tramite l'attributo MasterPageFile nella direttiva di ogni pagina del @Page contenuto.

La prima fase del ciclo di vita della pagina è la fase di inizializzazione. Durante questa fase la Page proprietà dell'oggetto MasterPageFile viene assegnato il valore dell'attributo MasterPageFile nella @Page direttiva (se specificato). La fase PreInit segue la fase di inizializzazione e viene impostata a livello di codice la Page proprietà dell'oggetto MasterPageFile , sovrascrivendo così il valore assegnato dalla @Page direttiva. Poiché si imposta la Page proprietà dell'oggetto MasterPageFile a livello di codice, è possibile rimuovere l'attributo MasterPageFile dalla @Page direttiva senza influire sull'esperienza dell'utente finale. Per convincere te stesso, andare avanti e rimuovere l'attributo MasterPageFile dalla @Page direttiva in Default.aspx e quindi visitare la pagina tramite un browser. Come si prevede, l'output è uguale a prima della rimozione dell'attributo.

Se la MasterPageFile proprietà viene impostata tramite la @Page direttiva o a livello di codice è inconsequentiale all'esperienza dell'utente finale. Tuttavia, l'attributo MasterPageFile nella direttiva viene usato da Visual Studio durante la @Page fase di progettazione per produrre la visualizzazione WYSIWYG nella Designer. Se si torna a Default.aspx In Visual Studio e si passa al Designer verrà visualizzato il messaggio "Errore pagina master: la pagina master include controlli che richiedono un riferimento alla pagina master, ma non è specificato alcuno" (vedere la figura 2).

In breve, è necessario lasciare l'attributo nella @Page direttiva per godere di un'esperienza MasterPageFile di progettazione avanzata in Visual Studio.

Visual Studio usa l'attributo MasterPageFile della direttiva <

Figura 02: Visual Studio usa l'attributo della MasterPageFile direttiva per eseguire il @Page rendering della visualizzazione progettazione (fare clic per visualizzare l'immagine full-size)

Passaggio 3: Creazione di una pagina master alternativa

Poiché la pagina master di una pagina del contenuto può essere impostata a livello di codice in fase di esecuzione, è possibile caricare dinamicamente una determinata pagina master in base a alcuni criteri esterni. Questa funzionalità può essere utile in situazioni in cui il layout del sito deve variare in base all'utente. Ad esempio, un'applicazione Web del motore di blog può consentire agli utenti di scegliere un layout per il blog, in cui ogni layout è associato a una pagina master diversa. In fase di esecuzione, quando un visitatore visualizza un blog di un utente, l'applicazione Web dovrà determinare il layout del blog e associare dinamicamente la pagina master corrispondente alla pagina del contenuto.

Si esaminerà come caricare dinamicamente una pagina master in fase di esecuzione in base a alcuni criteri esterni. Il nostro sito Web contiene attualmente una sola pagina master (Site.master). È necessaria un'altra pagina master per illustrare la scelta di una pagina master in fase di esecuzione. Questo passaggio è incentrato sulla creazione e la configurazione della nuova pagina master. Il passaggio 4 esamina la determinazione della pagina master da usare in fase di esecuzione.

Creare una nuova pagina master nella cartella radice denominata Alternate.master. Aggiungere anche un nuovo foglio di stile al sito Web denominato AlternateStyles.css.

Aggiungere un'altra pagina master e un file CSS al sito Web

Figura 03: Aggiungere un'altra pagina master e un file CSS al sito Web (fare clic per visualizzare l'immagine full-size)

Ho progettato la Alternate.master pagina master per avere il titolo visualizzato nella parte superiore della pagina, centrato e su uno sfondo marina. Ho dispensato della colonna sinistra e spostato il contenuto sotto il MainContent controllo ContentPlaceHolder, che ora si estende sull'intera larghezza della pagina. Inoltre, ho nixato l'elenco lezioni non ordinate e sostituito con un elenco orizzontale sopra MainContent. Ho anche aggiornato i tipi di carattere e i colori usati dalla pagina master (e, per estensione, le relative pagine di contenuto). La figura 4 mostra Default.aspx quando si usa la Alternate.master pagina master.

Nota

ASP.NET include la possibilità di definire temi. Un tema è una raccolta di immagini, file CSS e impostazioni delle proprietà di controllo Web correlate allo stile che possono essere applicate a una pagina in fase di esecuzione. I temi sono il modo per passare se i layout del sito differiscono solo nelle immagini visualizzate e dalle relative regole CSS. Se i layout differiscono in modo più significativo, ad esempio usando controlli Web diversi o con un layout radicalmente diverso, sarà necessario usare pagine master separate. Per altre informazioni sui temi, vedere la sezione Altre informazioni sulla lettura.

Le pagine di contenuto possono ora usare un nuovo aspetto e sentire

Figura 04: le pagine contenuto possono ora usare un nuovo aspetto e sentire (fare clic per visualizzare l'immagine a dimensioni complete)

Quando il markup delle pagine master e del contenuto viene fuso, la MasterPage classe verifica che ogni controllo Contenuto nella pagina del contenuto faccia riferimento a ContentPlaceHolder nella pagina master. Viene generata un'eccezione se viene trovato un controllo Content che fa riferimento a un contentPlaceHolder non esistente. In altre parole, è imperativo che la pagina master assegnata alla pagina del contenuto disponga di un ContentPlaceHolder per ogni controllo Contenuto nella pagina contenuto.

La Site.master pagina master include quattro controlli ContentPlaceHolder:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

Alcune pagine del contenuto nel nostro sito Web includono solo uno o due controlli Contenuto; altri includono un controllo Contenuto per ognuno dei ContentPlaceHolder disponibili. Se la nuova pagina master (Alternate.master) può essere assegnata a tali pagine di contenuto con controlli Contenuto per tutti i ContentPlaceHolder in Site.master , è essenziale Alternate.master includere anche gli stessi controlli ContentPlaceHolder come Site.master.

Per ottenere la Alternate.master pagina master come la mia (vedere la figura 4), iniziare definendo gli stili della pagina master nel AlternateStyles.css foglio di stile. Aggiungere le regole seguenti in 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; 
}

Aggiungere quindi il markup dichiarativo seguente a Alternate.master. Come si può notare, Alternate.master contiene quattro controlli ContentPlaceHolder con gli stessi ID valori dei controlli ContentPlaceHolder in Site.master. Include inoltre un controllo ScriptManager, necessario per tali pagine nel sito Web che usano il framework ASP.NET AJAX.

<!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>

Test della pagina Nuovo master

Per testare questa nuova pagina master, aggiornare il BasePage metodo della OnPreInit classe in modo che la MasterPageFile proprietà venga assegnata al valore "~/Alternate.master" e quindi visitare il sito Web. Ogni pagina deve funzionare senza errori ad eccezione di due: ~/Admin/AddProduct.aspx e ~/Admin/Products.aspx. L'aggiunta di un prodotto a DetailsView genera ~/Admin/AddProduct.aspx un NullReferenceException oggetto dalla riga di codice che tenta di impostare la proprietà della GridMessageText pagina master. Quando si visita ~/Admin/Products.aspx un oggetto InvalidCastException viene generato nel caricamento della pagina con il messaggio: "Impossibile eseguire il cast dell'oggetto di tipo 'ASP.alternate_master' per digitare 'ASP.site_master'".

Questi errori si verificano perché la Site.master classe code-behind include eventi, proprietà e metodi pubblici non definiti in Alternate.master. La parte di markup di queste due pagine ha una @MasterType direttiva che fa riferimento alla Site.master pagina master.

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

Inoltre, il gestore eventi ItemInserted di DetailsView in ~/Admin/AddProduct.aspx include il codice che esegue il cast della proprietà tipizzata Page.Master in modo libero a un oggetto di tipo Site. La @MasterType direttiva (utilizzata in questo modo) e il cast nel ItemInserted gestore eventi associa strettamente le ~/Admin/AddProduct.aspx pagine e ~/Admin/Products.aspx alla Site.master pagina master.

Per interrompere questo accoppiamento stretto, è possibile avere Site.master e Alternate.master derivare da una classe di base comune che contiene definizioni per i membri pubblici. In seguito, è possibile aggiornare la @MasterType direttiva per fare riferimento a questo tipo di base comune.

Creazione di una classe di pagina master di base personalizzata

Aggiungere un nuovo file di classe alla App_Code cartella denominata BaseMasterPage.cs e derivarlo da System.Web.UI.MasterPage. È necessario definire il metodo e la RefreshRecentProductsGridGridMessageText proprietà in BaseMasterPage, ma non è sufficiente spostarli da Site.master perché questi membri funzionano con i controlli Web specifici della Site.master pagina master ( RecentProducts GridView e GridMessage Label).

Ciò che è necessario fare è configurare BaseMasterPage in modo tale che questi membri siano definiti, ma vengono effettivamente implementati dalle BaseMasterPageclassi derivate (Site.master e Alternate.master). Questo tipo di ereditarietà è possibile contrassegnando la classe e i relativi membri come abstract. In breve, l'aggiunta della abstract parola chiave a questi due membri annuncia che BaseMasterPage non è stata implementata RefreshRecentProductsGrid e GridMessageText, ma che le relative classi derivate verranno eseguite.

È anche necessario definire l'evento PricesDoubled in BaseMasterPage e fornire un mezzo dalle classi derivate per generare l'evento. Il modello usato in .NET Framework per facilitare questo comportamento consiste nel creare un evento pubblico nella classe di base e aggiungere un metodo protetto denominato virtualOnEventName. Le classi derivate possono quindi chiamare questo metodo per generare l'evento o eseguirne l'override per eseguire il codice immediatamente prima o dopo la generazione dell'evento.

Aggiornare la BaseMasterPage classe in modo che contenga il codice seguente:

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; 
    } 
}

Passare quindi alla Site.master classe code-behind e derivare da BaseMasterPage. Poiché BaseMasterPage è abstract necessario eseguire l'override di tali abstract membri qui in Site.master. Aggiungere la parola chiave alle definizioni di override metodo e proprietà. Aggiornare anche il codice che genera l'evento PricesDoubled nel DoublePrice gestore eventi button Click con una chiamata al metodo della OnPricesDoubled classe base.

Dopo queste modifiche, la Site.master classe code-behind deve contenere il codice seguente:

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);
    } 
}

È anche necessario aggiornare Alternate.masterla classe code-behind per derivare da BaseMasterPage e sostituire i due abstract membri. Ma perché Alternate.master non contiene un oggetto GridView che elenca i prodotti più recenti o un'etichetta che visualizza un messaggio dopo l'aggiunta di un nuovo prodotto al database, questi metodi non devono eseguire alcuna operazione.

public partial class Alternate : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        // Do nothing 
    } 
    public override string GridMessageText 
    { 
        get
        { 
            return string.Empty;
        } 
        set
        {
            // Do nothing 
        } 
    }
}

Riferimento alla classe di pagina master di base

Dopo aver completato la classe e avere le due pagine master estese, il passaggio finale consiste nell'aggiornare BaseMasterPage le ~/Admin/AddProduct.aspx pagine e ~/Admin/Products.aspx per fare riferimento a questo tipo comune. Iniziare modificando la direttiva in entrambe le @MasterType pagine da:

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

Con:

<%@ MasterType TypeName="BaseMasterPage" %>

Anziché fare riferimento a un percorso file, la @MasterType proprietà fa ora riferimento al tipo di base (BaseMasterPage). Di conseguenza, la proprietà fortemente tipizzata Master usata nelle classi code-behind di entrambe le pagine è ora di tipo BaseMasterPage (anziché tipo Site). Con questa modifica in luogo rivedere ~/Admin/Products.aspx. In precedenza, questo ha generato un errore di cast perché la pagina è configurata per l'uso della Alternate.master pagina master, ma la @MasterType direttiva ha fatto riferimento al Site.master file. Ma ora la pagina viene eseguita senza errori. Questa operazione è dovuta al fatto che la Alternate.master pagina master può essere eseguita come cast in un oggetto di tipo BaseMasterPage (poiché si estende).

C'è una piccola modifica che deve essere apportata in ~/Admin/AddProduct.aspx. Il gestore eventi del ItemInserted controllo DetailsView usa sia la proprietà fortemente tipizzata che la proprietà tipizzata MasterPage.Master . È stato risolto il riferimento fortemente tipizzato quando è stata aggiornata la @MasterType direttiva, ma è comunque necessario aggiornare il riferimento con tipo libero. Sostituire la riga di codice seguente:

Site myMasterPage = Page.Master as Site;

Con quanto segue, che esegue Page.Master il cast al tipo di base:

BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;

Passaggio 4: Determinazione della pagina master da associare alle pagine del contenuto

La BasePage classe imposta attualmente tutte le proprietà delle MasterPageFile pagine del contenuto su un valore hardcoded nella fase PreInit del ciclo di vita della pagina. È possibile aggiornare questo codice per basare la pagina master su un fattore esterno. Forse la pagina master da caricare dipende dalle preferenze dell'utente attualmente connesso. In questo caso, è necessario scrivere codice nel OnPreInit metodo in BasePage cui cerca le preferenze della pagina master dell'utente attualmente in visita.

Verrà creata una pagina Web che consente all'utente di scegliere quale pagina master usare Site.master o Alternate.master salvare questa scelta in una variabile Sessione. Iniziare creando una nuova pagina Web nella directory radice denominata ChooseMasterPage.aspx. Quando si crea questa pagina (o qualsiasi altra pagina di contenuto) non è necessario associarla a una pagina master perché la pagina master è impostata a livello di codice in BasePage. Tuttavia, se non si associa la nuova pagina a una pagina master, il markup dichiarativo predefinito della nuova pagina contiene un Web Form e altri contenuti forniti dalla pagina master. Sarà necessario sostituire manualmente questo markup con i controlli Contenuto appropriati. Per questo motivo, trovo più facile associare la nuova pagina ASP.NET a una pagina master.

Nota

Poiché Site.master e Alternate.master avere lo stesso set di controlli ContentPlaceHolder non importa quale pagina master scegliere durante la creazione della nuova pagina di contenuto. Per coerenza, è consigliabile usare Site.master.

Aggiungere una nuova pagina contenuto al sito Web

Figura 05: Aggiungere una nuova pagina contenuto al sito Web (fare clic per visualizzare l'immagine full-size)

Aggiornare il Web.sitemap file in modo da includere una voce per questa lezione. Aggiungere il markup seguente sotto per <siteMapNode> le pagine master e ASP.NET lezione AJAX:

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

Prima di aggiungere qualsiasi contenuto alla ChooseMasterPage.aspx pagina, è necessario aggiornare la classe code-behind della pagina in modo che deriva da BasePage (anziché System.Web.UI.Page). Aggiungere quindi un controllo DropDownList alla pagina, impostarne la ID proprietà su MasterPageChoicee aggiungere due ListItems con i Text valori di "~/Site.master" e "~/Alternate.master".

Aggiungere rispettivamente un controllo Web Button alla pagina e impostarne IDText le proprietà e su SaveLayout e "Salva scelta layout". A questo punto il markup dichiarativo della pagina dovrebbe essere simile al seguente:

<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>

Quando la pagina viene prima visitata, è necessario visualizzare la scelta della pagina master attualmente selezionata dall'utente. Creare un Page_Load gestore eventi e aggiungere il codice seguente:

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; 
        } 
    }
}

Il codice precedente viene eseguito solo nella prima pagina visita (e non nei postback successivi). Verifica prima di tutto se esiste la variabile MyMasterPage Session. In caso affermativo, tenta di trovare l'oggetto ListItem corrispondente nell'elenco MasterPageChoice a discesa. Se viene trovato un oggetto ListItem corrispondente, la relativa Selected proprietà è impostata su true.

È necessario anche il codice che salva la scelta dell'utente nella MyMasterPage variabile Sessione. Creare un gestore eventi per l'evento SaveLayoutClick Button e aggiungere il codice seguente:

protected void SaveLayout_Click(object sender, EventArgs e)
{
    Session["MyMasterPage"] = MasterPageChoice.SelectedValue;
    Response.Redirect("ChooseMasterPage.aspx"); 
}

Nota

Al momento dell'esecuzione del Click gestore eventi nel postback, la pagina master è già stata selezionata. Pertanto, la selezione dell'elenco a discesa dell'utente non sarà effettiva fino alla visita della pagina successiva. Forza Response.Redirect il browser a richiedere ChooseMasterPage.aspxnuovamente .

Al termine della pagina, l'attività ChooseMasterPage.aspx finale consiste nell'assegnare BasePage la MasterPageFile proprietà in base al valore della MyMasterPage variabile Session. Se la variabile Session non è impostata come BasePage predefinita su 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(); 
}

Nota

È stato spostato il codice che assegna la Page proprietà dell'oggetto MasterPageFile al di fuori del OnPreInit gestore eventi e in due metodi separati. Questo primo metodo, SetMasterPageFile, assegna la MasterPageFile proprietà al valore restituito dal secondo metodo , GetMasterPageFileFromSession. Il metodo virtual è stato eseguito in modo che le classi future che estendono BasePage possono eseguire facoltativamente l'override per implementare la SetMasterPageFile logica personalizzata, se necessario. Verrà visualizzato un esempio della proprietà di SetMasterPageFile override BasePagenell'esercitazione successiva.

Con questo codice sul posto, visitare la ChooseMasterPage.aspx pagina. Inizialmente, la Site.master pagina master è selezionata (vedere la figura 6), ma l'utente può scegliere una pagina master diversa dall'elenco a discesa.

Le pagine di contenuto vengono visualizzate usando la pagina master site.master

Figura 06: le pagine contenuto vengono visualizzate usando la pagina master (fare clic per visualizzare l'immagineSite.master a dimensioni complete)

Le pagine di contenuto vengono ora visualizzate usando la pagina master alternate.master

Figura 07: Le pagine contenuto vengono ora visualizzate usando la pagina master (fare clic per visualizzare l'immagineAlternate.master a dimensioni complete)

Riepilogo

Quando viene visitata una pagina di contenuto, i controlli Contenuto vengono fusi con i controlli ContentPlaceHolder della pagina master. La pagina master della pagina del contenuto viene denotata dalla Page proprietà della MasterPageFile classe, assegnata all'attributo MasterPageFile della direttiva durante la @Page fase di inizializzazione. Come illustrato in questa esercitazione, è possibile assegnare un valore alla MasterPageFile proprietà purché venga eseguita prima della fine della fase PreInit. La possibilità di specificare a livello di codice la pagina master apre la porta per scenari più avanzati, ad esempio l'associazione dinamica di una pagina contenuto a una pagina master in base a fattori esterni.

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, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore 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 speciale a

Questa serie di esercitazioni è stata esaminata da molti revisori utili. Il revisore principale di questa esercitazione è Stato Suchi Banerjee. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com