Compartilhar via


Páginas mestras aninhadas (C#)

por Scott Mitchell

Mostra como aninhar uma página mestra em outra.

Introdução

Ao longo dos últimos nove tutoriais, vimos como implementar um layout em todo o site com páginas mestras. Em poucas palavras, as páginas mestras permitem que nós, o desenvolvedor da página, defina a marcação comum na página mestra junto com regiões específicas que podem ser personalizadas em uma base de página de conteúdo por página de conteúdo. Os controles ContentPlaceHolder em uma página mestra indicam as regiões personalizáveis; a marcação personalizada para os controles ContentPlaceHolder é definida na página de conteúdo por meio de controles de conteúdo.

As técnicas de página mestra que exploramos até agora são ótimas se você tiver um único layout usado em todo o site. No entanto, muitos sites grandes têm um layout de site personalizado em várias seções. Por exemplo, considere um aplicativo de assistência médica usado pela equipe do hospital para gerenciar informações, atividades e faturamento do paciente. Pode haver três tipos de páginas da web neste aplicativo:

  • Páginas específicas de membros da equipe onde os membros da equipe podem atualizar a disponibilidade, exibir agendas ou solicitar férias.
  • Páginas específicas do paciente onde os membros da equipe visualizam ou editam informações de um paciente específico.
  • Páginas específicas de faturamento em que os contadores analisam os status atuais dos sinistros e os relatórios financeiros.

Cada página pode compartilhar um layout comum, como um menu na parte superior e uma série de links usados com frequência na parte inferior. Mas as páginas específicas da equipe, do paciente e da cobrança podem precisar personalizar esse layout genérico. Por exemplo, talvez todas as páginas específicas da equipe devam incluir um calendário e uma lista de tarefas mostrando a disponibilidade e a programação diária do usuário conectado no momento. Talvez todas as páginas específicas do paciente precisem mostrar o nome, endereço e informações de seguro do paciente cujas informações estão sendo editadas.

É possível criar esses layouts personalizados usando páginas mestras aninhadas. Para implementar o cenário acima, começaríamos criando uma página mestra que definisse o layout de todo o site, o menu e o conteúdo do rodapé, com ContentPlaceHolders definindo as regiões personalizáveis. Em seguida, criaríamos três páginas mestras aninhadas, uma para cada tipo de página da Web. Cada página mestra aninhada definiria o conteúdo entre o tipo de páginas de conteúdo que usam a página mestra. Em outras palavras, a página mestra aninhada para páginas de conteúdo específicas do paciente incluiria marcação e lógica programática para exibir informações sobre o paciente que está sendo editado. Ao criar uma nova página específica do paciente, nós a vincularíamos a essa página mestra aninhada.

Este tutorial começa destacando os benefícios das páginas mestras aninhadas. Em seguida, mostra como criar e usar páginas mestras aninhadas.

Observação

As páginas mestras aninhadas são possíveis desde a versão 2.0 do .NET Framework. No entanto, o Visual Studio 2005 não incluiu suporte em tempo de design para páginas mestras aninhadas. A boa notícia é que o Visual Studio 2008 oferece uma experiência avançada de tempo de design para páginas mestras aninhadas. Se você estiver interessado em usar páginas mestras aninhadas, mas ainda estiver usando o Visual Studio 2005, confira a entrada de blog de Scott Guthrie, Dicas para páginas mestras aninhadas no VS 2005 Design-Time.

Os benefícios das páginas mestras aninhadas

Muitos sites têm um design de site abrangente, bem como designs mais personalizados específicos para determinados tipos de páginas. Por exemplo, em nosso aplicativo da web de demonstração, criamos uma seção de administração rudimentar (as páginas na ~/Admin pasta). Atualmente, as páginas da Web na ~/Admin pasta usam a mesma página mestra que as páginas que não estão na seção de administração (ou seja, Site.master ou Alternate.master, dependendo da seleção do usuário).

Observação

Por enquanto, finja que nosso site tem apenas uma página mestra, Site.master. Abordaremos o uso de páginas mestras aninhadas com duas (ou mais) páginas mestras, começando com "Usando uma página mestra aninhada para a seção Administração" mais adiante neste tutorial.

Imagine que nos foi pedido para personalizar o layout das páginas de Administração para incluir informações adicionais ou links que, de outra forma, não estariam presentes em outras páginas do site. Há quatro técnicas para implementar esse requisito:

  1. Adicione manualmente as informações e os links específicos da Administração a todas as páginas de conteúdo da ~/Admin pasta.
  2. Atualize a Site.master página mestra para incluir as informações e os links específicos da seção Administração e, em seguida, adicione código à página mestra para mostrar ou ocultar essas seções com base no fato de uma das páginas de Administração estar sendo visitada.
  3. Crie uma nova página mestra especificamente para a seção Administração, copie a marcação de Site.master, adicione as informações e os links específicos da seção Administração e atualize as ~/Admin páginas de conteúdo na pasta para usar essa nova página mestra.
  4. Crie uma página mestra aninhada que seja associada e Site.master faça com que as páginas de conteúdo na ~/Admin pasta usem essa nova página mestra aninhada. Essa página mestra aninhada incluiria apenas as informações adicionais e os links específicos das páginas de Administração e não precisaria repetir a marcação já definida no Site.master.

A primeira opção é a menos palatável. O objetivo de usar páginas mestras é deixar de ter que copiar e colar manualmente a marcação comum em novas páginas ASP.NET. A segunda opção é aceitável, mas torna o aplicativo menos sustentável, pois aumenta as páginas mestras com marcação que é exibida apenas ocasionalmente e exige que os desenvolvedores que editam a página mestra contornem essa marcação e tenham que lembrar quando, exatamente, determinada marcação é exibida versus quando ela está oculta. Essa abordagem seria menos sustentável, pois as personalizações de mais e mais tipos de páginas da Web precisavam ser acomodadas por essa única página mestra.

A terceira opção remove os problemas de desordem e complexidade que surgiram com a segunda opção. No entanto, a principal desvantagem da opção três é que ela exige que copiemos e colemos o layout comum da nova página mestra específica da Site.master seção Administração. Se mais tarde decidirmos alterar o layout de todo o site, temos que nos lembrar de alterá-lo em dois lugares.

A quarta opção, páginas mestras aninhadas, nos dá o melhor da segunda e terceira opções. As informações de layout de todo o site são mantidas em um arquivo - a página mestra de nível superior - enquanto o conteúdo específico de regiões específicas é separado em arquivos diferentes.

Este tutorial começa com uma olhada na criação e no uso de uma página mestra aninhada simples. Criamos uma nova página mestra de nível superior, duas páginas mestras aninhadas e duas páginas de conteúdo. Começando com "Usando uma página mestra aninhada para a seção de administração", examinamos a atualização de nossa arquitetura de página mestra existente para incluir o uso de páginas mestras aninhadas. Especificamente, criamos uma página mestra aninhada e a usamos para incluir conteúdo personalizado adicional para as páginas de conteúdo na ~/Admin pasta.

Etapa 1: Criando uma página mestra simples de nível superior

Criar um mestre aninhado com base em uma das páginas mestras existentes e, em seguida, atualizar uma página de conteúdo existente para usar essa nova página mestra aninhada em vez da página mestra de nível superior envolve alguma complexidade porque as páginas de conteúdo existentes já esperam determinados controles ContentPlaceHolder definidos na página mestra de nível superior. Portanto, a página mestra aninhada também deve incluir os mesmos controles ContentPlaceHolder com os mesmos nomes. Além disso, nosso aplicativo de demonstração específico tem duas páginas mestras (Site.master e Alternate.master) que são atribuídas dinamicamente a uma página de conteúdo com base nas preferências do usuário, o que aumenta ainda mais essa complexidade. Veremos como atualizar o aplicativo existente para usar páginas mestras aninhadas posteriormente neste tutorial, mas vamos primeiro nos concentrar em um exemplo simples de páginas mestras aninhadas.

Crie uma nova pasta chamada NestedMasterPages e adicione um novo arquivo de página mestra a essa pasta chamada Simple.master. (Consulte a Figura 1 para obter uma captura de tela do Gerenciador de Soluções depois que essa pasta e arquivo forem adicionados.) Arraste o AlternateStyles.css arquivo de folha de estilos do Gerenciador de Soluções para o Designer. Isso adiciona um <link> elemento ao arquivo de folha de estilo no elemento, após o <head> qual a marcação do <head> elemento da página mestra deve ser semelhante a:

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

Em seguida, adicione a seguinte marcação no formulário da Web de 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>

Essa marcação exibe um link intitulado "Páginas mestras aninhadas (simples)" na parte superior da página em uma fonte branca grande em um plano de fundo azul-marinho. Abaixo disso está o MainContent ContentPlaceHolder. A Figura 1 mostra a Simple.master página mestra quando carregada no Visual Studio Designer.

A página mestra de ponto simples quando carregada no Visual Studio Designer.

Figura 01: A página mestra aninhada define o conteúdo específico das páginas na seção Administração (clique para exibir a imagem em tamanho real)

Etapa 2: Criando uma página mestra aninhada simples

Simple.master contém dois controles ContentPlaceHolder: o MainContent ContentPlaceHolder que adicionamos no formulário da Web junto com o head ContentPlaceHolder no <head> elemento. Se fôssemos criar uma página de conteúdo e associá-la à Simple.master página de conteúdo, teríamos dois controles de conteúdo referenciando os dois ContentPlaceHolders. Da mesma forma, se criarmos uma página mestra aninhada e a associarmos a Simple.master ela, a página mestra aninhada terá dois controles de conteúdo.

Vamos adicionar uma nova página mestra aninhada NestedMasterPages à pasta chamada SimpleNested.master. Clique com o botão direito do NestedMasterPages mouse na pasta e escolha Adicionar novo item. Isso abre a caixa de diálogo Adicionar novo item mostrada na Figura 2. Selecione o tipo de modelo de Página Mestra e digite o nome da nova página mestra. Para indicar que a nova página mestra deve ser uma página mestra aninhada, marque a caixa de seleção "Selecionar página mestra".

Em seguida, clique no botão Adicionar. Isso exibirá a mesma caixa de diálogo Selecionar uma página mestra que você vê ao vincular uma página de conteúdo a uma página mestra (consulte a Figura 3). Escolha a Simple.master página mestra na pasta e clique em NestedMasterPages OK.

Observação

Se você criou seu site ASP.NET usando o modelo de Projeto de Aplicativo Web em vez do modelo de Projeto de Site, não verá a caixa de seleção "Selecionar página mestra" na caixa de diálogo Adicionar Novo Item mostrada na Figura 2. Para criar uma página mestra aninhada ao usar o modelo de Projeto de Aplicação Web, você deve escolher o modelo de Página Mestra Aninhada (em vez do modelo de Página Mestra). Depois de selecionar o modelo de Página Mestra Aninhada e clicar em Adicionar, a mesma caixa de diálogo Selecionar uma Página Mestre mostrada na Figura 3 será exibida.

Marque a caixa de seleção

Figura 02: Marque a caixa de seleção "Selecionar página mestra" para adicionar uma página mestra aninhada (clique para exibir a imagem em tamanho real)

Associar a página mestra aninhada à página mestra Simple.master

Figura 03: Associar a página mestra aninhada à página mestra (clique para exibir a Simple.master imagem em tamanho real)

A marcação declarativa da página mestra aninhada, mostrada abaixo, contém dois controles Content que fazem referência aos dois controles ContentPlaceHolder da página mestra de nível superior.

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

Exceto pela <%@ Master %> diretiva, a marcação declarativa inicial da página mestra aninhada é idêntica à marcação gerada inicialmente ao associar uma página de conteúdo à mesma página mestra de nível superior. Como a diretiva de uma página de <%@ Page %> conteúdo, a <%@ Master %> diretiva aqui inclui um MasterPageFile atributo que especifica a página mestra pai da página mestra aninhada. A principal diferença entre a página mestra aninhada e uma página de conteúdo associada à mesma página mestra de nível superior é que a página mestra aninhada pode incluir controles ContentPlaceHolder. Os controles ContentPlaceHolder da página mestra aninhada definem as regiões em que as páginas de conteúdo podem personalizar a marcação.

Atualize essa página mestra aninhada para que ela exiba o texto "Olá, de SimpleNested!" no controle Content que corresponde ao MainContent controle ContentPlaceHolder.

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

Depois de fazer essa adição, salve a página mestra aninhada e adicione uma nova página de conteúdo à NestedMasterPages pasta chamada Default.aspx, e vincule-a SimpleNested.master à página mestra. Ao adicionar esta página, você pode se surpreender ao ver que ela não contém controles de conteúdo (consulte a Figura 4)! Uma página de conteúdo só pode acessar os ContentPlaceHolders da página mestra pai . SimpleNested.master não contém nenhum controle ContentPlaceHolder; portanto, qualquer página de conteúdo associada a essa página mestra não pode conter nenhum controle de conteúdo.

A nova página de conteúdo não contém controles de conteúdo

Figura 04: A nova página de conteúdo não contém controles de conteúdo (clique para exibir a imagem em tamanho real)

O que precisamos fazer é atualizar a página mestra aninhada (SimpleNested.master) para incluir controles ContentPlaceHolder. Normalmente, você desejará que suas páginas mestras aninhadas incluam um ContentPlaceHolder para cada ContentPlaceHolder definido por sua página mestra pai, permitindo assim que sua página mestra filho ou página de conteúdo funcione com qualquer um dos controles ContentPlaceHolder da página mestra de nível superior.

Atualize a SimpleNested.master página mestra para incluir um ContentPlaceHolder em seus dois controles de conteúdo. Dê aos controles ContentPlaceHolder o mesmo nome que o controle ContentPlaceHolder ao qual seu controle Content se refere. Ou seja, adicione um controle ContentPlaceHolder nomeado MainContent ao controle Content em SimpleNested.master que faz referência ao MainContent ContentPlaceHolder em Simple.master. Faça a mesma coisa no controle Content que faz referência ao head ContentPlaceHolder.

Observação

Embora eu recomende nomear os controles ContentPlaceHolder na página mestra aninhada da mesma forma que os ContentPlaceHolders na página mestra de nível superior, essa simetria de nomenclatura não é necessária. Você pode dar aos controles ContentPlaceHolder em sua página mestra aninhada qualquer nome que desejar. No entanto, acho mais fácil lembrar quais ContentPlaceHolders correspondem a quais regiões da página se minha página mestra de nível superior e páginas mestras aninhadas usarem os mesmos nomes.

Depois de fazer essas adições, a marcação declarativa da página SimpleNested.master mestra deve ser semelhante à seguinte:

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

Exclua a Default.aspx página de conteúdo que acabamos de criar e adicione-a novamente, vinculando-a SimpleNested.master à página mestra. Desta vez, o Default.aspxVisual Studio adiciona dois controles de conteúdo ao , referenciando os ContentPlaceHolders agora definidos em SimpleNested.master (consulte a Figura 6). Adicione o texto "Olá, do Default.aspx!" no controle de conteúdo que fez referência MainContenta .

A Figura 5 mostra as três entidades envolvidas aqui - Simple.master, , SimpleNested.mastere Default.aspx - e como elas se relacionam entre si. Como mostra o diagrama, a página mestra aninhada implementa controles de conteúdo para o ContentPlaceHolder de seu pai. Se essas regiões precisarem ser acessíveis à página de conteúdo, a página mestra aninhada deverá adicionar seus próprios ContentPlaceHolders aos controles de conteúdo.

As páginas mestras de nível superior e aninhadas ditam o layout da página de conteúdo

Figura 05: As páginas mestras de nível superior e aninhadas ditam o layout da página de conteúdo (clique para exibir a imagem em tamanho real)

Esse comportamento ilustra como uma página de conteúdo ou página mestra só reconhece sua página mestra pai. Esse comportamento também é indicado pelo Visual Studio Designer. A Figura 6 mostra o Designer para Default.aspx. Embora o Designer mostre claramente quais regiões são editáveis na página de conteúdo e quais partes não são, ele não elimina a ambiguidade de quais regiões não editáveis são da página mestra aninhada e quais regiões são da página mestra de nível superior.

A página de conteúdo agora inclui controles de conteúdo para os ContentPlaceHolders da página mestra aninhada

Figura 06: A página de conteúdo agora inclui controles de conteúdo para os ContentPlaceHolders da página mestra aninhada (clique para exibir a imagem em tamanho real)

Etapa 3: Adicionando uma segunda página mestra aninhada simples

O benefício das páginas mestras aninhadas é mais evidente quando há várias páginas mestras aninhadas. Para ilustrar esse benefício, crie outra página mestra aninhada NestedMasterPages na pasta; nomeie essa nova página SimpleNestedAlternate.master mestra aninhada e vincule-a Simple.master à página mestra. Adicione controles ContentPlaceHolder nos dois controles Content da página mestra aninhada, como fizemos na Etapa 2. Adicione também o texto "Olá, de SimpleNestedAlternate!" no controle Content que corresponde ao ContentPlaceHolder da MainContent página mestra de nível superior. Depois de fazer essas alterações, a marcação declarativa da nova página mestra aninhada deve ser semelhante à seguinte:

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

Crie uma página de conteúdo nomeada Alternate.aspx na NestedMasterPages pasta e associe-a SimpleNestedAlternate.master à página mestra aninhada. Adicione o texto "Olá, da alternativa!" no controle de conteúdo que corresponde a MainContent. A Figura 7 mostra Alternate.aspx quando exibida por meio do Visual Studio Designer.

Alternate.aspx está associado à página mestra SimpleNestedAlternate.master

Figura 07: Alternate.aspx está acoplado à página mestra (clique para exibir a SimpleNestedAlternate.master imagem em tamanho real)

Compare o designer na Figura 7 com o designer na Figura 6. Ambas as páginas de conteúdo compartilham o mesmo layout definido na página mestra de nível superior (Simple.master), ou seja, o título "Tutorial de Páginas Mestras Aninhadas (Simples)". No entanto, ambos têm conteúdo distinto definido em suas páginas mestras pai - o texto "Olá, de SimpleNested!" na Figura 6 e "Olá, de SimpleNestedAlternate!" na Figura 7. É verdade que essas diferenças aqui são triviais, mas você pode estender este exemplo para incluir diferenças mais significativas. Por exemplo, a SimpleNested.master página pode incluir um menu com opções específicas para suas páginas de conteúdo, enquanto SimpleNestedAlternate.master pode ter informações pertinentes às páginas de conteúdo que se vinculam a ela.

Agora, imagine que precisássemos fazer uma alteração no layout geral do site. Por exemplo, imagine que quiséssemos adicionar uma lista de links comuns a todas as páginas de conteúdo. Para fazer isso, atualizamos a página mestra de nível superior, Simple.master. Todas as alterações são refletidas imediatamente em suas páginas mestras aninhadas e, por extensão, em suas páginas de conteúdo.

Para demonstrar a facilidade com que podemos alterar o layout do site abrangente, abra a Simple.master página mestra e adicione a seguinte marcação entre os topContent elementos and 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>

Isso adiciona dois links à parte superior de cada página que se vincula a Simple.master, SimpleNested.master, ou SimpleNestedAlternate.master; essas alterações se aplicam a todas as páginas mestras aninhadas e suas páginas de conteúdo imediatamente. A Figura 8 mostra Alternate.aspx quando visualizada por meio de um navegador. Observe a adição dos links na parte superior da página (em comparação com a Figura 7).

Alteradas para a página mestra de nível superior são refletidas imediatamente em suas páginas mestras aninhadas e suas páginas de conteúdo

Figura 08: Alteradas para a página mestra de nível superior são refletidas imediatamente em suas páginas mestras aninhadas e suas páginas de conteúdo (clique para exibir a imagem em tamanho real)

Usando uma página mestra aninhada para a seção Administração

Neste ponto, examinamos as vantagens das páginas mestras aninhadas e vimos como criá-las e usá-las em um aplicativo ASP.NET. Os exemplos nas Etapas 1, 2 e 3, no entanto, envolveram a criação de uma nova página mestra de nível superior, novas páginas mestras aninhadas e novas páginas de conteúdo. Que tal adicionar uma nova página mestra aninhada a um site com uma página mestra de nível superior e páginas de conteúdo existentes?

Integrar uma página mestra aninhada a um site existente e associá-la a páginas de conteúdo existentes requer um pouco mais de esforço do que começar do zero. As etapas 4, 5, 6 e 7 exploram esses desafios à medida que aumentamos nosso aplicativo de demonstração para incluir uma nova página mestra aninhada chamada AdminNested.master que contém instruções para o administrador e é usada pelas páginas ASP.NET na ~/Admin pasta.

A integração de uma página mestra aninhada em nosso aplicativo de demonstração apresenta os seguintes obstáculos:

  • As páginas de conteúdo existentes na ~/Admin pasta têm certas expectativas de sua página mestra. Para começar, eles esperam que determinados controles ContentPlaceHolder estejam presentes. Além disso, as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx chamam o método público RefreshRecentProductsGrid da página mestra, definem sua GridMessageText propriedade ou têm um manipulador de eventos para seu PricesDoubled evento. Consequentemente, nossa página mestra aninhada deve fornecer os mesmos ContentPlaceHolders e membros públicos.
  • No tutorial anterior, aprimoramos a BasePage classe para definir dinamicamente a Page propriedade do MasterPageFile objeto com base em uma variável Session. Como podemos oferecer suporte a páginas mestras dinâmicas ao usar páginas mestras aninhadas?

Esses dois desafios surgirão à medida que criarmos a página mestra aninhada e a usarmos em nossas páginas de conteúdo existentes. Investigaremos e superaremos esses problemas à medida que surgirem.

Etapa 4: Criando a página mestra aninhada

Nossa primeira tarefa é criar a página mestra aninhada a ser usada pelas páginas na seção Administração. Como vimos na Etapa 2, ao adicionar uma nova página mestra aninhada, precisamos especificar a página mestra pai da página mestra aninhada. Mas temos duas páginas mestras de nível superior: Site.master e Alternate.master. Lembre-se de que criamos Alternate.master no tutorial anterior e escrevemos código BasePage na classe que define a propriedade do MasterPageFile objeto Page em runtime como ou Site.master Alternate.master dependendo do valor da MyMasterPage variável Session.

Como configuramos nossa página mestra aninhada para que ela use a página mestra de nível superior apropriada? Nós temos duas opções:

  • Crie duas páginas AdminNestedSite.master mestras aninhadas e AdminNestedAlternate.master, e vincule-as às páginas Site.master mestras de nível superior e Alternate.master, respectivamente. Em BasePage, então, definiríamos o Page objeto MasterPageFile para a página mestra aninhada apropriada.
  • Crie uma única página mestra aninhada e faça com que as páginas de conteúdo usem essa página mestra específica. Em seguida, em tempo de execução, precisaríamos definir a propriedade da MasterPageFile página mestra aninhada como a página mestra de nível superior apropriada em tempo de execução. (Como você já deve ter percebido, as páginas mestras também têm uma MasterPageFile propriedade.)

Vamos usar a segunda opção. Crie um único arquivo de página mestra aninhado ~/Admin na pasta chamada AdminNested.master. Como ambos Site.master Alternate.master têm o mesmo conjunto de controles ContentPlaceHolder, não importa a qual página mestra você o vincule, embora eu o encoraje a associá-lo Site.master por uma questão de consistência.

Adicione uma página mestra aninhada à pasta ~/admin.

Figura 09: Adicionar uma página mestra aninhada à ~/Admin pasta. (Clique para ver a imagem em tamanho real)

Como a página mestra aninhada está associada a uma página mestra com quatro controles ContentPlaceHolder, o Visual Studio adiciona quatro controles Content à marcação inicial do novo arquivo de página mestra aninhada. Como fizemos nas Etapas 2 e 3, adicione um controle ContentPlaceHolder em cada controle Content, dando a ele o mesmo nome que o controle ContentPlaceHolder da página mestra de nível superior. Adicione também a seguinte marcação ao controle Content que corresponde ao 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>

Em seguida, defina a instructions classe CSS nos Styles.css arquivos e AlternateStyles.css CSS. As seguintes regras CSS fazem com que os elementos HTML estilizados com a instructions classe sejam exibidos com uma cor de fundo amarela clara e uma borda preta sólida:

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

Como essa marcação foi adicionada à página mestra aninhada, ela só aparecerá nas páginas que usam essa página mestra aninhada (ou seja, as páginas na seção Administração).

Depois de fazer essas adições à sua página mestra aninhada, sua marcação declarativa deve ser semelhante à seguinte:

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

Observe que cada controle Content tem um controle ContentPlaceHolder e que as propriedades dos ID controles ContentPlaceHolder recebem os mesmos valores que os controles ContentPlaceHolder correspondentes na página mestra de nível superior. Além disso, a marcação específica da seção Administração aparece no MainContent ContentPlaceHolder.

A Figura 10 mostra a AdminNested.master página mestra aninhada quando exibida por meio do Designer do Visual Studio. Você pode ver as instruções na caixa amarela na parte superior do MainContent controle Conteúdo.

A página mestra aninhada estende a página mestra de nível superior para incluir instruções para o administrador.

Figura 10: A página mestra aninhada estende a página mestra de nível superior para incluir instruções para o administrador. (Clique para ver a imagem em tamanho real)

Etapa 5: Atualizando as páginas de conteúdo existentes para usar a nova página mestra aninhada

Sempre que adicionamos uma nova página de conteúdo à seção Administração, precisamos vinculá-la à AdminNested.master página mestra que acabamos de criar. Mas e as páginas de conteúdo existentes? Atualmente, todas as páginas de conteúdo no site derivam da BasePage classe, que define programaticamente a página mestra da página de conteúdo em runtime. Esse não é o comportamento que queremos para as páginas de conteúdo na seção Administração. Em vez disso, queremos que essas páginas de conteúdo sempre usem a AdminNested.master página. Será responsabilidade da página mestra aninhada escolher a página de conteúdo de nível superior correta em runtime.

A melhor maneira de obter esse comportamento desejado é criar uma nova classe de página base personalizada chamada AdminBasePage que estende a BasePage classe. AdminBasePage pode então substituir e SetMasterPageFile definir o Page objeto MasterPageFile como o valor codificado "~/Admin/AdminNested.master". Dessa forma, qualquer página derivada de AdminBasePage usará AdminNested.master, enquanto qualquer página derivada de BasePage terá sua MasterPageFile propriedade definida dinamicamente como "~/Site.master" ou "~/Alternate.master" com base no valor da MyMasterPage variável Session.

Comece adicionando um novo arquivo de classe à App_Code pasta chamada AdminBasePage.cs. Ter AdminBasePage extend BasePage e, em seguida, substituir o SetMasterPageFile método. Nesse método, atribua o MasterPageFile valor "~/Admin/AdminNested.master". Depois de fazer essas alterações, seu arquivo de classe deve ser semelhante ao seguinte:

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

Agora precisamos que as páginas de conteúdo existentes na seção Administração derivem de em vez de AdminBasePage BasePage. Vá para o arquivo de classe code-behind para cada página de conteúdo na ~/Admin pasta e faça essa alteração. Por exemplo, você ~/Admin/Default.aspx alteraria a declaração de classe code-behind de:

public partial class Admin_Default : BasePage

Para:

public partial class Admin_Default : AdminBasePage

A Figura 11 mostra como a página mestra de nível superior (Site.master ou Alternate.master), a página mestra aninhada (AdminNested.master) e as páginas de conteúdo da seção Administração se relacionam entre si.

A página mestra aninhada define o conteúdo específico das páginas na seção Administração

Figura 11: A página mestra aninhada define o conteúdo específico das páginas na seção Administração (clique para exibir a imagem em tamanho real)

Etapa 6: Espelhando os métodos e propriedades públicas da página mestra

Lembre-se de que as ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx interagem programaticamente com a página mestra: ~/Admin/AddProduct.aspx chama o método public RefreshRecentProductsGrid da página mestra e define sua GridMessageText propriedade; ~/Admin/Products.aspx tem um manipulador de eventos para o PricesDoubled evento. No tutorial anterior, criamos uma classe abstrata BaseMasterPage que definiu esses membros públicos.

As ~/Admin/AddProduct.aspx páginas e ~/Admin/Products.aspx pressupõem que sua página mestra deriva da BaseMasterPage classe. A AdminNested.master página, no entanto, atualmente estende a System.Web.UI.MasterPage classe. Como resultado, ao visitar ~/Admin/Products.aspx um InvalidCastException é lançado com a mensagem: "Não é possível converter o objeto do tipo 'ASP.admin_adminnested_master' para o tipo 'BaseMasterPage'".

Para corrigir isso, precisamos fazer com que a AdminNested.master classe code-behind estenda BaseMasterPage. Atualize a declaração de classe code-behind da página mestra aninhada de:

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

Para:

public partial class Admin_AdminNested : BaseMasterPage

Ainda não terminamos. Como a BaseMasterPage classe é abstrata, precisamos substituir os abstract membros RefreshRecentProductsGrid e GridMessageText. Esses membros são usados pelas páginas mestras de nível superior para atualizar suas interfaces do usuário. (Na verdade, apenas a página mestra usa esses métodos, embora ambas as Site.master páginas mestras de nível superior implementem esses métodos, já que ambas se estendem BaseMasterPage.)

Embora precisemos implementar esses membros no AdminNested.master, tudo o que essas implementações precisam fazer é simplesmente chamar o mesmo membro na página mestra de nível superior usada pela página mestra aninhada. Por exemplo, quando uma página de conteúdo na seção Administração chama o método da RefreshRecentProductsGrid página mestra aninhada, tudo o que a página mestra aninhada precisa fazer é, por sua vez, chamar Site.master o Alternate.mastermétodo ou RefreshRecentProductsGrid .

Para conseguir isso, comece adicionando a seguinte @MasterType diretiva ao topo de AdminNested.master:

<%@ MasterType TypeName="BaseMasterPage" %>

Lembre-se de que a @MasterType diretiva adiciona uma propriedade fortemente tipada à classe code-behind chamada Master. Em seguida, substitua os RefreshRecentProductsGrid membros and GridMessageText e simplesmente delegue a chamada ao Mastermétodo correspondente do :

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

Com esse código em vigor, você poderá visitar e usar as páginas de conteúdo na seção Administração. A Figura 12 mostra a página quando visualizada ~/Admin/Products.aspx por meio de um navegador. Como você pode ver, a página inclui a caixa Instruções de Administração, que é definida na página mestra aninhada.

As páginas de conteúdo na seção Administração incluem instruções na parte superior de cada página

Figura 12: As páginas de conteúdo na seção Administração incluem instruções na parte superior de cada página (clique para exibir a imagem em tamanho real)

Etapa 7: Usando a página mestra de nível superior apropriada em tempo de execução

Embora todas as páginas de conteúdo na seção Administração sejam totalmente funcionais, todas elas usam a mesma página mestra de nível superior e ignoram a página mestra selecionada pelo usuário em ChooseMasterPage.aspx. Esse comportamento se deve ao fato de que a página mestra aninhada tem sua MasterPageFile propriedade definida estaticamente como Site.master em sua <%@ Master %> diretiva.

Para usar a página mestra de nível superior selecionada pelo usuário final, precisamos definir a AdminNested.masterpropriedade do MasterPageFile como o valor na MyMasterPage variável Session. Como definimos as propriedades das MasterPageFile páginas de conteúdo em BasePage, você pode pensar que definiríamos a propriedade da MasterPageFile página mestra aninhada na BaseMasterPage classe code-behind da AdminNested.master. Isso não funcionará, no entanto, porque precisamos definir a MasterPageFile propriedade até o final do estágio PreInit. A primeira vez que podemos tocar programaticamente no ciclo de vida da página a partir de uma página mestra é o estágio Init (que ocorre após o estágio PreInit).

Portanto, precisamos definir a propriedade da MasterPageFile página mestra aninhada nas páginas de conteúdo. As únicas páginas de conteúdo que usam a AdminNested.master página mestra derivam de AdminBasePage. Portanto, podemos colocar essa lógica lá. Na Etapa 5, substituímos o SetMasterPageFile método, definindo a Page propriedade do MasterPageFile objeto como "~/Admin/AdminNested.master". Atualize SetMasterPageFile para definir também a propriedade da MasterPageFile página mestra como o resultado armazenado em Sessão:

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

O GetMasterPageFileFromSession método, que adicionamos à BasePage classe no tutorial anterior, retorna o caminho apropriado do arquivo de paginação mestra com base no valor da variável Session.

Com essa alteração em vigor, a seleção da página mestra do usuário é transferida para a seção Administração. A Figura 13 mostra a mesma página que a Figura 12, mas depois que o usuário alterou sua seleção de página mestra para Alternate.master.

A página de administração aninhada usa a página mestra de nível superior selecionada pelo usuário

Figura 13: A página de administração aninhada usa a página mestra de nível superior selecionada pelo usuário (clique para exibir a imagem em tamanho real)

Resumo

Assim como as páginas de conteúdo podem ser associadas a uma página mestra, é possível criar páginas mestras aninhadas fazendo com que uma página mestra filho seja associada a uma página mestra pai. A página mestra filho pode definir controles de conteúdo para cada um dos ContentPlaceHolders de seu pai; em seguida, ele pode adicionar seus próprios controles ContentPlaceHolder (bem como outras marcações) a esses controles de conteúdo. As páginas mestras aninhadas são bastante úteis em grandes aplicativos da Web em que todas as páginas compartilham uma aparência abrangente, mas certas seções do site exigem personalizações exclusivas.

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. Interessado em revisar meus próximos artigos do MSDN? Se sim, me mande uma mensagem em mitchell@4GuysFromRolla.com