Especificar a página mestra programaticamente (VB)

por Scott Mitchell

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

Introdução

Desde o exemplo inaugural em Criando um layout de Site-Wide usando páginas mestras, todas as páginas de conteúdo referenciaram seus master página 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.mastermaster :

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

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

Neste tutorial, adicionamos uma segunda página master ao nosso site e decidimos dinamicamente qual master página usar em runtime.

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 mesclar os controles de Conteúdo da página nos controles ContentPlaceHolder correspondentes da página master. Essa fusão cria uma única hierarquia de controle que pode prosseguir com o 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 master hierarquias de controle de página. No final do estágio PreInit, os controles de conteúdo na página são adicionados aos ContentPlaceHolders correspondentes na página master (Etapa 2). Após essa fusão, a página master serve como a raiz da hierarquia de controle fundida. Essa hierarquia de controle fundida é 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 do 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 pré-inicial (clique para exibir a imagem em tamanho real)

Etapa 2: Definindo a propriedade doMasterPageFilecódigo

O que master página participa nessa 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 durante MasterPageFile o estágio 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 objeto aciona seu PagePreInit evento e chama seu OnPreInit método . Para definir a página master 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.vb, o arquivo de classe code-behind da home page 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" para a 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 Default.aspx página for visitada ou sempre que houver um postback nessa 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 master em uma página específica, mas sim de BasePage. Lembre-se de que criamos uma classe de página base personalizada (BasePage) de volta no tutorial Especificando o título, meta tags e outros cabeçalhos HTML na página mestra . Atualmente BasePage , substitui o Page método da OnLoadComplete classe, em que ele define a propriedade da Title página com base nos dados do mapa do site. Vamos atualizar BasePage para também substituir o OnPreInit método para especificar programaticamente a página master.

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 master atribuída programaticamente. Neste ponto, o PreInit manipulador de eventos em Default.aspx.vb é supérfluo; fique à 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 locais: 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 do ciclo de vida da página é o estágio 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 inicialização e é aqui que definimos programaticamente a Page propriedade do MasterPageFile objeto, substituindo assim o valor atribuído da @Page diretiva . Como estamos definindo a Page propriedade do MasterPageFile objeto programaticamente, poderíamos 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 atributo da @Page diretiva em Default.aspx e visite a página por meio de um navegador. Como você esperaria, a saída é a mesma de antes de o atributo ser removido.

Se a MasterPageFile propriedade é definida por meio da @Page diretiva ou programaticamente é inconsequente à experiência do usuário final. No entanto, o MasterPageFile atributo na @Page diretiva é usado pelo Visual Studio durante o tempo de design para produzir a exibição WYSIWYG no Designer. Se você retornar ao Default.aspx no 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 nenhum é especificado" (consulte a Figura 2).

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

Visual Studio Usa o atributo MasterPageFile da diretiva <span class=@Page para renderizar a exibição de design" />

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

Etapa 3: Criando uma página mestra alternativa

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

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

Crie uma nova página master na pasta raiz chamada Alternate.master. Adicione também uma nova folha de estilos ao site chamado 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 master para que o título seja exibido na parte superior da página, centralizado e em um plano de fundo da marinha. Dispensei a coluna esquerda e movai esse conteúdo abaixo do MainContent controle ContentPlaceHolder, que agora abrange toda a largura da página. Além disso, cancelei a lista lições não ordenadas e a substituí por uma lista horizontal acima MainContentde . Também atualizei as fontes e as cores usadas pela página master (e, por extensão, suas páginas de conteúdo). A Figura 4 mostra Default.aspx ao usar a Alternate.master página master.

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 runtime. Os temas são o caminho a percorrer se os layouts do seu site diferem apenas nas imagens exibidas e pelas regras de CSS. Se os layouts forem mais substancialmente diferentes, como usar controles da Web diferentes ou ter um layout radicalmente diferente, você precisará usar páginas master 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 de conteúdo e master estiverem fundidas, a MasterPage classe verificará se todos os controles de Conteúdo na página de conteúdo referenciam um ContentPlaceHolder na página master. Uma exceção será gerada se um controle Content que faz referência a um ContentPlaceHolder inexistente for encontrado. Em outras palavras, é imperativo que a página master 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 master 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 de master (Alternate.master) puder ser atribuída às páginas de conteúdo que têm controles de conteúdo para todos os ContentPlaceHolders no Site.master , é essencial que Alternate.master também inclua os mesmos controles ContentPlaceHolder que Site.master.

Para que sua Alternate.master página de master seja semelhante à minha (consulte a Figura 4), comece definindo os estilos da página master na AlternateStyles.css 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 em Site.master. Além disso, ele inclui um controle ScriptManager, que é necessário para as páginas em 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 esse novo master página atualize o BasePage método da OnPreInit classe para que a MasterPageFile propriedade seja atribuída ao valor "~/Alternate.maser" e, em seguida, visite o site. Cada página deve funcionar sem erro, exceto por dois: ~/Admin/AddProduct.aspx e ~/Admin/Products.aspx. Adicionar um produto ao DetailsView resulta em ~/Admin/AddProduct.aspx um NullReferenceException da linha de código que tenta definir a propriedade da GridMessageText página master. Ao visitar ~/Admin/Products.aspx um InvalidCastException é gerado no carregamento da página com a mensagem: "Não é possível converter o objeto do tipo 'ASP.alternate_master' para digitar 'ASP.site_master'."

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

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

Além disso, o manipulador de eventos do ItemInserted DetailsView no ~/Admin/AddProduct.aspx inclui o 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 associam firmemente as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx à Site.master página master.

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

Criando uma classe de página mestra base personalizada

Adicione um novo arquivo de classe à App_Code pasta chamada 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 da Web específicos para a Site.master página master (GridView RecentProducts e GridMessage Label).

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

Também precisamos definir o PricesDoubled evento em BaseMasterPage e fornecer um meio pelas classes derivadas para acionar 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 acionar o evento ou podem substituí-lo para executar o código imediatamente antes ou depois que o evento é acionado.

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 o Overrides palavra-chave às definições de método e propriedade. Atualize também o código que aciona o PricesDoubled evento no DoublePrice manipulador de eventos do Click Botão 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 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 classe e temos nossas duas páginas master estendendo-a, nossa etapa final é atualizar as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx para fazer referência 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 referenciar um caminho de arquivo, a @MasterType propriedade agora faz referência ao tipo base (BaseMasterPage). Consequentemente, a propriedade fortemente tipada Master usada nas classes code-behind de ambas as páginas agora é do tipo BaseMasterPage (em vez do tipo Site). Com essa alteração em vigor, reveja ~/Admin/Products.aspx. Anteriormente, isso resultava em um erro de conversão porque a página estava configurada para usar a Alternate.master página master, 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 master pode ser convertida em um objeto do tipo BaseMasterPage (já que a estende).

Há uma pequena alteração que precisa ser feita em ~/Admin/AddProduct.aspx. O manipulador de eventos do ItemInserted 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 de tipo flexível. Substitua a seguinte linha de código:

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

Com o seguinte, que é convertido Page.Master no tipo base:

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

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

Atualmente, nossa BasePage classe define todas as propriedades de 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 master em algum fator externo. Talvez a página master a ser carregada dependa das preferências do usuário conectado no momento. Nesse caso, precisamos escrever código no OnPreInit método em BasePage que pesquisa as preferências de página de master do usuário que está visitando no momento.

Vamos criar uma página da Web que permita que o usuário escolha qual master página usar - Site.master ou Alternate.master - e salvar essa opção em uma variável de sessão. Comece criando uma nova página da Web no diretório raiz chamado ChooseMasterPage.aspx. Ao criar essa página (ou outras páginas de conteúdo a partir de agora), você não precisa associá-la a uma página master porque a página master é definida programaticamente em BasePage. No entanto, se você não associar a nova página a uma página master, a marcação declarativa padrão da nova página conterá um Web Form e outro conteúdo fornecido pela página master. Você precisará substituir manualmente essa marcação pelos controles de Conteúdo apropriados. Por esse motivo, acho mais fácil associar a nova página de ASP.NET a uma página master.

Observação

Como Site.master e Alternate.master têm o mesmo conjunto de controles ContentPlaceHolder, não importa qual master página 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 de <siteMapNode> para a lição Páginas Mestras e ASP.NET AJAX:

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

Antes de adicionar qualquer conteúdo à ChooseMasterPage.aspx página, reserve um momento para atualizar a classe code-behind da página para que ela seja derivada de (em vez System.Web.UI.Pagede BasePage ). Em seguida, adicione um controle DropDownList à página, defina sua ID propriedade MasterPageChoicecomo e 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 e "Salvar Escolha de Layout", respectivamente. Neste ponto, a marcação declarativa da 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 master do usuário selecionada no momento. Crie um Page_Load manipulador de 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 somente na primeira visita à página (e não em postbacks subsequentes). Primeiro, ele verifica se a variável MyMasterPage Session existe. Se isso acontecer, ele tentará encontrar o ListItem correspondente no MasterPageChoice DropDownList. Se um ListItem correspondente for encontrado, sua Selected propriedade será definida Truecomo .

Também precisamos de código que salve a escolha do usuário na MyMasterPage variável De sessão. Crie um manipulador de eventos para o SaveLayout evento do Click Botão 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 master já foi selecionada. Portanto, a seleção de lista suspensa do usuário não estará em vigor até a próxima visita à página. O Response.Redirect força o navegador a solicitar ChooseMasterPage.aspxnovamente .

Com a ChooseMasterPage.aspx página concluída, nossa tarefa final é atribuir BasePage 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

Movai o código que atribui a Page propriedade do MasterPageFile objeto para fora do OnPreInit manipulador de eventos e para dois métodos separados. Esse primeiro método, SetMasterPageFile, atribui a MasterPageFile propriedade ao valor retornado pelo segundo método, GetMasterPageFileFromSession. Marquei o SetMasterPageFile método Overridable para que 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 SetMasterPageFile no próximo tutorial.

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

As Páginas de Conteúdo são exibidas usando o site. Página Mestra do master

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

As páginas de conteúdo agora são exibidas usando o alternativo. Página Mestra do master

Figura 07: As páginas de conteúdo agora são exibidas usando a Alternate.master página mestra (clique para exibir a 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 master. A página master 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 inicialização. Como este tutorial mostrou, podemos atribuir um valor à MasterPageFile propriedade desde que façamos isso antes do final do estágio PreInit. Ser capaz de especificar programaticamente a página master abre a porta para cenários mais avançados, como associar dinamicamente uma página de conteúdo a uma página master com base em fatores externos.

Programação feliz!

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 do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. 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

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? Nesse caso, solte-me uma linha em mitchell@4GuysFromRolla.com