Compartilhar via


Especificar a página mestra programaticamente (VB)

por Scott Mitchell

Examina a configuração da página mestra da página de conteúdo programaticamente por meio do manipulador de eventos PreInit.

Introdução

Desde o exemplo inaugural em Criando um layout em todo o site usando páginas mestras, todas as páginas de conteúdo referenciaram sua página mestra declarativamente por meio do MasterPageFile atributo na @Page diretiva. Por exemplo, a seguinte @Page diretiva vincula a página de conteúdo à página Site.mastermestra:

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

A classe no namespace inclui umaMasterPageFile propriedade que retorna o caminho para a página mestra da página de conteúdo; é essa propriedade que é definida pela @Page diretiva.System.Web.UIPage Essa propriedade também pode ser usada para especificar programaticamente a página mestra da página de conteúdo. Essa abordagem é útil se você quiser atribuir dinamicamente a página mestra com base em fatores externos, como o usuário que visita a página.

Neste tutorial, adicionamos uma segunda página mestra ao nosso site e decidimos dinamicamente qual página mestra usar no tempo de execução.

Etapa 1: uma olhada no ciclo de vida da página

Sempre que uma solicitação chega ao servidor Web para uma página ASP.NET que é uma página de conteúdo, o mecanismo de ASP.NET deve fundir os controles de conteúdo da página nos controles ContentPlaceHolder correspondentes da página mestra. Essa fusão cria uma única hierarquia de controle que pode prosseguir pelo ciclo de vida típico da página.

A Figura 1 ilustra essa fusão. A etapa 1 na Figura 1 mostra o conteúdo inicial e as hierarquias de controle de página mestra. No final do estágio PreInit, os controles de conteúdo na página são adicionados aos ContentPlaceHolders correspondentes na página mestra (Etapa 2). Após essa fusão, a página mestra serve como a raiz da hierarquia de controle fundida. Essa hierarquia de controle fundida é então adicionada à página para produzir a hierarquia de controle finalizada (Etapa 3). O resultado líquido é que a hierarquia de controle da página inclui a hierarquia de controle fundida.

As hierarquias de controle da página mestra e da página de conteúdo são fundidas durante o estágio de pré-inicialização

Figura 01: As hierarquias de controle da página mestra e da página de conteúdo são fundidas durante o estágio de pré-inicialização (clique para exibir a imagem em tamanho real)

Etapa 2: Definindo aMasterPageFilepropriedade do código

A página mestra que participa dessa fusão depende do valor da Page propriedade do MasterPageFile objeto. Definir o MasterPageFile atributo na @Page diretiva tem o efeito líquido de atribuir a Pagepropriedade do durante MasterPageFile o estágio de inicialização, que é o primeiro estágio do ciclo de vida da página. Como alternativa, podemos definir essa propriedade programaticamente. No entanto, é imperativo que essa propriedade seja definida antes que a fusão na Figura 1 ocorra.

No início do estágio PreInit, o Page objeto gera seu PreInit evento e chama seu OnPreInit método. Para definir a página mestra programaticamente, podemos criar um manipulador de eventos para o PreInit evento ou substituir o OnPreInit método. Vamos examinar as duas abordagens.

Comece abrindo Default.aspx.vbo , o arquivo de classe code-behind para a página inicial do nosso site. Adicione um manipulador de eventos para o evento da PreInit página digitando o seguinte código:

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
End Sub

A partir daqui, podemos definir a MasterPageFile propriedade. Atualize o código para que ele atribua o valor "~/Site.master" à MasterPageFile propriedade.

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

Se você definir um ponto de interrupção e começar com a depuração, verá que sempre que a página for visitada Default.aspx ou sempre que houver um postback para essa página, o Page_PreInit manipulador de eventos será executado e a MasterPageFile propriedade será atribuída a "~/Site.master".

Como alternativa, você pode substituir o Page método da OnPreInit classe e definir a MasterPageFile propriedade lá. Para este exemplo, não vamos definir a página mestra em uma página específica, mas sim a partir de BasePage. Lembre-se de que criamos uma classe de página base personalizada (BasePage) no tutorial Especificando o título, as metatags e outros cabeçalhos HTML na página mestra. Atualmente BasePage , substitui o Page método da OnLoadComplete classe, em que define a propriedade da Title página com base nos dados do mapa do site. Vamos atualizar BasePage para substituir também o OnPreInit método para especificar programaticamente a página mestra.

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

Como todas as nossas páginas de conteúdo derivam de BasePage, todas elas agora têm sua página mestra atribuída programaticamente. Neste ponto, o PreInit manipulador de eventos é Default.aspx.vb supérfluo; sinta-se à vontade para removê-lo.

E quanto à@Pagediretiva?

O que pode ser um pouco confuso é que as propriedades das MasterPageFile páginas de conteúdo agora estão sendo especificadas em dois lugares: programaticamente no BasePage método da OnPreInit classe, bem como por meio do MasterPageFile atributo na diretiva de cada página de @Page conteúdo.

O primeiro estágio no ciclo de vida da página é o estágio de inicialização. Durante esse estágio, a Page propriedade do MasterPageFile objeto recebe o valor do MasterPageFile atributo na @Page diretiva (se for fornecido). O estágio PreInit segue o estágio Initialization e é aqui que definimos programaticamente a propriedade do Page MasterPageFile objeto, substituindo assim o valor atribuído pela @Page diretiva. Como estamos definindo a Page propriedade do MasterPageFile objeto programaticamente, podemos remover o MasterPageFile atributo da @Page diretiva sem afetar a experiência do usuário final. Para se convencer disso, vá em frente e remova o MasterPageFile @Page atributo da diretiva e Default.aspx visite a página por meio de um navegador. Como seria de esperar, a saída é a mesma de antes da remoção do atributo.

Se a MasterPageFile propriedade é definida por meio da @Page diretiva ou programaticamente, não é irrelevante para a experiência do usuário final. No entanto, o MasterPageFile atributo na diretiva é usado pelo Visual Studio durante o @Page tempo de design para produzir o modo de exibição WYSIWYG no Designer. Se você retornar ao Default.aspx Visual Studio e navegar até o Designer, verá a mensagem "Erro de Página Mestra: a página tem controles que exigem uma referência de Página Mestra, mas nenhuma é especificada" (consulte a Figura 2).

Em resumo, você precisa deixar o MasterPageFile atributo na @Page diretiva para desfrutar de uma experiência avançada de tempo de design no Visual Studio.

O Visual Studio usa a classe <span=@Page atributo MasterPageFile da diretiva para renderizar o modo de exibição de design" />

Figura 02: O Visual Studio usa o @Page atributo da MasterPageFile diretiva para renderizar o modo de exibição de design (clique para exibir a imagem em tamanho real)

Etapa 3: Criando uma página mestra alternativa

Como a página mestra de uma página de conteúdo pode ser definida programaticamente em runtime, é possível carregar dinamicamente uma página mestra específica com base em alguns critérios externos. Essa funcionalidade pode ser útil em situações em que o layout do site precisa variar de acordo com o usuário. Por exemplo, um aplicativo da Web do mecanismo de blog pode permitir que seus usuários escolham um layout para seu blog, onde cada layout está associado a uma página mestra diferente. Em tempo de execução, quando um visitante está exibindo o blog de um usuário, o aplicativo Web precisaria determinar o layout do blog e associar dinamicamente a página mestra correspondente à página de conteúdo.

Vamos examinar como carregar dinamicamente uma página mestra em tempo de execução com base em alguns critérios externos. Nosso site atualmente contém apenas uma página mestra (Site.master). Precisamos de outra página mestra para ilustrar a escolha de uma página mestra em tempo de execução. Esta etapa se concentra na criação e configuração da nova página mestra. A etapa 4 examina como determinar qual página mestra usar em runtime.

Crie uma nova página mestra na pasta raiz chamada Alternate.master. Adicione também uma nova folha de estilo ao site chamada AlternateStyles.css.

Adicionar outra página mestra e arquivo CSS ao site

Figura 03: Adicionar outra página mestra e arquivo CSS ao site (clique para exibir a imagem em tamanho real)

Eu projetei a Alternate.master página mestra para que o título seja exibido na parte superior da página, centralizado e em um plano de fundo azul-marinho. Dispensei a coluna da esquerda e movi esse conteúdo para baixo do MainContent controle ContentPlaceHolder, que agora abrange toda a largura da página. Além disso, eliminei a lista de lições não ordenada e a substituí por uma lista horizontal acima MainContent. Também atualizei as fontes e cores usadas pela página mestra (e, por extensão, suas páginas de conteúdo). A Figura 4 mostra Default.aspx ao usar a Alternate.master página mestra.

Observação

ASP.NET inclui a capacidade de definir temas. Um Tema é uma coleção de imagens, arquivos CSS e configurações de propriedade de controle da Web relacionadas ao estilo que podem ser aplicadas a uma página em tempo de execução. Os temas são o caminho a percorrer se os layouts do seu site diferirem apenas nas imagens exibidas e por suas regras CSS. Se os layouts forem mais substancialmente diferentes, como usar controles Web diferentes ou ter um layout radicalmente diferente, você precisará usar páginas mestras separadas. Consulte a seção Leitura Adicional no final deste tutorial para obter mais informações sobre Temas.

Nossas páginas de conteúdo agora podem usar uma nova aparência

Figura 04: Nossas páginas de conteúdo agora podem usar uma nova aparência (clique para exibir a imagem em tamanho real)

Quando a marcação das páginas mestra e de conteúdo é fundida, a MasterPage classe verifica se cada controle de conteúdo na página de conteúdo faz referência a um ContentPlaceHolder na página mestra. Uma exceção será gerada se um controle de conteúdo que faz referência a um ContentPlaceHolder inexistente for encontrado. Em outras palavras, é imperativo que a página mestra que está sendo atribuída à página de conteúdo tenha um ContentPlaceHolder para cada controle de conteúdo na página de conteúdo.

A Site.master página mestra inclui quatro controles ContentPlaceHolder:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

Algumas das páginas de conteúdo em nosso site incluem apenas um ou dois controles de conteúdo; outros incluem um controle de conteúdo para cada um dos ContentPlaceHolders disponíveis. Se nossa nova página mestra (Alternate.master) puder ser atribuída às páginas de conteúdo que têm controles de conteúdo para todos os ContentPlaceHolders Site.master , é essencial que Alternate.master também inclua os mesmos controles Site.masterContentPlaceHolder que .

Para que sua Alternate.master página mestra seja semelhante à minha (consulte a AlternateStyles.css Figura 4), comece definindo os estilos da página mestra na folha de estilos. Adicione as seguintes regras em 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;
}

Em seguida, adicione a seguinte marcação declarativa a Alternate.master. Como você pode ver, Alternate.master contém quatro controles ContentPlaceHolder com os mesmos ID valores que os controles ContentPlaceHolder no Site.master. Além disso, inclui um controle ScriptManager, que é necessário para as páginas do nosso site que usam a estrutura 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>

Testando a nova página mestra

Para testar essa nova página mestra, atualize o BasePage método da OnPreInit classe para que a MasterPageFile propriedade receba o valor "~/Alternate.maser" e, em seguida, visite o site. Todas as páginas devem funcionar sem erros, exceto duas: ~/Admin/AddProduct.aspx e ~/Admin/Products.aspx. Adicionar um produto ao DetailsView em resulta em ~/Admin/AddProduct.aspx uma NullReferenceException linha de código que tenta definir a propriedade da GridMessageText página mestra. Ao visitar ~/Admin/Products.aspx um InvalidCastException é lançado no carregamento da página com a mensagem: "Não é possível converter o objeto do tipo 'ASP.alternate_master' para o tipo 'ASP.site_master'."

Esses erros ocorrem porque a Site.master classe code-behind inclui eventos públicos, propriedades e métodos que não estão definidos no Alternate.master. A parte de marcação dessas duas páginas tem uma @MasterType diretiva que faz referência à Site.master página mestra.

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

Além disso, o manipulador de ItemInserted eventos do DetailsView inclui ~/Admin/AddProduct.aspx código que converte a propriedade de tipo Page.Master flexível em um objeto do tipo Site. A @MasterType diretiva (usada dessa forma) e a conversão no ItemInserted manipulador de eventos acoplam firmemente as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx à Site.master página mestra.

Para quebrar esse acoplamento rígido, podemos ter Site.master e Alternate.master derivar de uma classe base comum que contém definições para os membros públicos. Em seguida, podemos atualizar a @MasterType diretiva para fazer referência a esse tipo de base comum.

Criando uma classe de página mestra base personalizada

Adicione um novo arquivo de classe à App_Code pasta nomeada BaseMasterPage.vb e faça com que ele derive de System.Web.UI.MasterPage. Precisamos definir o RefreshRecentProductsGrid método e a GridMessageText propriedade em BaseMasterPage, mas não podemos simplesmente movê-los para lá porque Site.master esses membros trabalham com controles Web específicos da Site.master página mestra (o GridView e GridMessage o RecentProducts Label).

O que precisamos fazer é configurar BaseMasterPage de tal forma que esses membros sejam definidos lá, mas na verdade sejam implementados pelas BaseMasterPageclassesSite.master derivadas de ( e Alternate.master). Esse tipo de herança é possível marcando a classe como MustInherit e seus membros como MustOverride. Resumindo, adicionar essas palavras-chave à classe e seus dois membros anuncia que BaseMasterPage não implementou RefreshRecentProductsGrid e GridMessageText, mas que suas classes derivadas o farão.

Também precisamos definir o PricesDoubled evento e BaseMasterPage fornecer um meio pelas classes derivadas para gerar o evento. O padrão usado no .NET Framework para facilitar esse comportamento é criar um evento público na classe base e adicionar um método protegido e substituível chamado OnEventName. As classes derivadas podem chamar esse método para gerar o evento ou substituí-lo para executar o código imediatamente antes ou depois que o evento for gerado.

Atualize sua BaseMasterPage classe para que ela contenha o seguinte código:

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

Em seguida, vá para a Site.master classe code-behind e faça com que ela derive de BaseMasterPage. Como BaseMasterPage contém membros marcados MustOverride , precisamos substituir esses membros aqui no Site.master. Adicione a Overrides palavra-chave às definições de método e propriedade. Atualize também o código que gera o PricesDoubled evento no DoublePrice manipulador de Click eventos do Button com uma chamada para o método da OnPricesDoubled classe base.

Após essas modificações, a Site.master classe code-behind deve conter o seguinte código:

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

Também precisamos atualizar Alternate.mastera classe code-behind de para derivar BaseMasterPage e substituir os dois MustOverride membros. Mas como Alternate.master não contém um GridView que lista os produtos mais recentes nem um Label que exibe uma mensagem depois que um novo produto é adicionado ao banco de dados, esses métodos não precisam fazer nada.

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

Referenciando a classe de página mestra base

Agora que concluímos a BaseMasterPage aula e temos nossas duas páginas mestras estendendo-a, nossa etapa final é atualizar as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx para se referir a esse tipo comum. Comece alterando a @MasterType diretiva em ambas as páginas de:

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

Para:

<%@ MasterType TypeName="BaseMasterPage" %>

Em vez de fazer referência a um caminho de arquivo, a @MasterType propriedade agora faz referência ao tipo base (BaseMasterPage). Conseqüentemente, a propriedade fortemente tipada Master usada nas classes code-behind de ambas as páginas agora é do tipo BaseMasterPage (em vez de tipo Site). Com essa mudança de lugar, revisite ~/Admin/Products.aspx. Anteriormente, isso resultava em um erro de conversão porque a página está configurada para usar a Alternate.master página mestra, mas a @MasterType diretiva fazia referência ao Site.master arquivo. Mas agora a página é renderizada sem erros. Isso ocorre porque a Alternate.master página mestra pode ser convertida em um objeto do tipo BaseMasterPage (já que ela a estende).

Há uma pequena mudança que precisa ser feita no ~/Admin/AddProduct.aspx. O manipulador de ItemInserted eventos do controle DetailsView usa a propriedade fortemente tipada Master e a propriedade de tipo Page.Master flexível. Corrigimos a referência fortemente tipada quando atualizamos a @MasterType diretiva, mas ainda precisamos atualizar a referência vagamente tipada. Substitua a seguinte linha de código:

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

Com o seguinte, que converte Page.Master para o tipo base:

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

Etapa 4: Determinando qual página mestra vincular às páginas de conteúdo

Atualmente, nossa BasePage classe define todas as propriedades das MasterPageFile páginas de conteúdo como um valor embutido em código no estágio PreInit do ciclo de vida da página. Podemos atualizar esse código para basear a página mestra em algum fator externo. Talvez a página mestra a ser carregada dependa das preferências do usuário conectado no momento. Nesse caso, precisaríamos escrever código no OnPreInit método BasePage que pesquisa as preferências da página mestra do usuário que está visitando no momento.

Vamos criar uma página da Web que permita ao usuário escolher qual página mestra usar - Site.master ou Alternate.master - e salvar essa opção em uma variável Session. Comece criando uma nova página da Web no diretório raiz chamada ChooseMasterPage.aspx. Ao criar esta página (ou qualquer outra página de conteúdo a partir de agora), você não precisa vinculá-la a uma página mestra porque a página mestra é definida programaticamente em BasePage. No entanto, se você não vincular a nova página a uma página mestra, a marcação declarativa padrão da nova página conterá um formulário da Web e outros conteúdos fornecidos pela página mestra. Você precisará substituir manualmente essa marcação pelos controles de conteúdo apropriados. Por esse motivo, acho mais fácil vincular a nova página ASP.NET a uma página mestra.

Observação

Porque Site.master e Alternate.master ter o mesmo conjunto de controles ContentPlaceHolder, não importa qual página mestra você escolher ao criar a nova página de conteúdo. Para consistência, sugiro usar Site.master.

Adicionar uma nova página de conteúdo ao site

Figura 05: Adicionar uma nova página de conteúdo ao site (clique para exibir a imagem em tamanho real)

Atualize o Web.sitemap arquivo para incluir uma entrada para esta lição. Adicione a seguinte marcação abaixo da <siteMapNode> lição para as Páginas Mestras e ASP.NET AJAX:

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

Antes de adicionar qualquer conteúdo à página, ChooseMasterPage.aspx reserve um momento para atualizar a classe code-behind da página para que ela derive de (em vez de BasePage System.Web.UI.Page). Em seguida, adicione um controle DropDownList à página, defina sua ID propriedade como MasterPageChoicee adicione dois ListItems com os Text valores de "~/Site.master" e "~/Alternate.master".

Adicione um controle Web de botão à página e defina suas ID propriedades e Text como SaveLayout "Salvar opção de layout", respectivamente. Neste ponto, a marcação declarativa da sua página deve ser semelhante à seguinte:

<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 a página é visitada pela primeira vez, precisamos exibir a opção de página mestra selecionada pelo usuário no momento. Crie um manipulador de Page_Load eventos e adicione o seguinte código:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 If Session("MyMasterPage") IsNot Nothing Then 
 Dim li As ListItem = MasterPageChoice.Items.FindByText(Session("MyMasterPage").ToString())
 If li IsNot Nothing Then 
 li.Selected = True
 End If 
 End If 
 End If 
End Sub

O código acima é executado apenas na primeira visita à página (e não em postbacks subsequentes). Primeiro, ele verifica se a variável MyMasterPage Session existe. Em caso afirmativo, ele tentará localizar o ListItem correspondente no MasterPageChoice DropDownList. Se um ListItem correspondente for encontrado, sua Selected propriedade será definida como True.

Também precisamos de código que salve a escolha do usuário na MyMasterPage variável Session. Crie um manipulador de Click eventos para o SaveLayout evento do Button e adicione o seguinte código:

Protected Sub SaveLayout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveLayout.Click 
 Session("MyMasterPage") = MasterPageChoice.SelectedValue 
 Response.Redirect("ChooseMasterPage.aspx")
End Sub

Observação

No momento em que o Click manipulador de eventos é executado no postback, a página mestra já foi selecionada. Portanto, a seleção da lista suspensa do usuário não estará em vigor até a próxima visita à página. Isso Response.Redirect força o navegador a solicitar ChooseMasterPage.aspxnovamente .

Com a ChooseMasterPage.aspx página concluída, nossa tarefa final é BasePage atribuir a MasterPageFile propriedade com base no valor da MyMasterPage variável Session. Se a variável Session não estiver definida, o padrão Site.masterserá BasePage .

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

Observação

Mudei o código que atribui a Page propriedade do MasterPageFile objeto para fora do OnPreInit manipulador de eventos e para dois métodos separados. Este primeiro método, SetMasterPageFile, atribui a MasterPageFile propriedade ao valor retornado pelo segundo método, GetMasterPageFileFromSession. Marquei o método Overridable para que as SetMasterPageFile classes futuras que se estendem BasePage possam opcionalmente substituí-lo para implementar a lógica personalizada, se necessário. Veremos um exemplo de substituição BasePageda propriedade de no SetMasterPageFile próximo tutorial.

Com esse código em vigor, visite a ChooseMasterPage.aspx página. Inicialmente, a Site.master página mestra é selecionada (consulte a Figura 6), mas o usuário pode escolher uma página mestra diferente na lista suspensa.

As páginas de conteúdo são exibidas usando a página mestra Site.master

Figura 06: As páginas de conteúdo são exibidas usando a página mestra (clique para exibir a Site.master imagem em tamanho real)

As páginas de conteúdo agora são exibidas usando a página mestra Alternate.master

Figura 07: As páginas de conteúdo agora são exibidas usando a página mestra (clique para exibir a Alternate.master imagem em tamanho real)

Resumo

Quando uma página de conteúdo é visitada, seus controles de conteúdo são fundidos com os controles ContentPlaceHolder da página mestra. A página mestra da página de conteúdo é indicada pela Page propriedade da MasterPageFile classe, que é atribuída ao @Page atributo da MasterPageFile diretiva durante o estágio de inicialização. Como este tutorial mostrou, podemos atribuir um valor à MasterPageFile propriedade, desde que o façamos antes do final do estágio PreInit. Ser capaz de especificar programaticamente a página mestra abre a porta para cenários mais avançados, como associar dinamicamente uma página de conteúdo a uma página mestra com base em fatores externos.

Boa programação!

Leitura Adicional

Para obter mais informações sobre os tópicos discutidos neste tutorial, consulte os seguintes recursos:

Sobre o autor

Scott Mitchell, autor de vários livros ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 3.5 em 24 horas. Scott pode ser contatado em mitchell@4GuysFromRolla.com ou através de seu blog em http://ScottOnWriting.NET.

Agradecimentos especiais a

Esta série de tutoriais foi revisada por muitos revisores úteis. O revisor principal deste tutorial foi Suchi Banerjee. Interessado em revisar meus próximos artigos do MSDN? Se sim, me mande uma mensagem em mitchell@4GuysFromRolla.com