11. O aplicativo [SimuPaie] – versão 7 – ASP.NET / múltiplas visualizações / múltiplas páginas
Leituras recomendadas: referência [1], Desenvolvimento WEB com ASP.NET 1.1 parágrafo: Exemplos
Analisaremos agora uma versão funcionalmente idêntica ao aplicativo ASP.NET de três camadas [pam-v4-3tier-nhibernate-multivues-monopage] estudado anteriormente, mas modificaremos a arquitetura deste último da seguinte maneira: enquanto na versão anterior as visualizações eram implementadas por uma única página ASPX, aqui elas serão implementadas por três páginas ASPX.
A arquitetura do aplicativo anterior era a seguinte:
![]() |
Aqui temos uma arquitetura MVC (Modelo – Visão – Controlador):
- [Default.aspx.cs] contém o código do controlador. A página [Default.aspx] é o único ponto de contato com o cliente. Ela recebe todas as solicitações do cliente.
- [Saisies, Simulation, Simulations, ...] são as visualizações. Essas visualizações são implementadas aqui por meio dos componentes [View] da página [Default.aspx].
A arquitetura da nova versão será a seguinte:
![]() |
- apenas a camada [web] sofre alterações
- as visualizações (o que é exibido ao usuário) não mudam.
- O código do controlador, que na versão anterior estava inteiramente no [Default.aspx.cs], agora está distribuído por várias páginas:
- [MasterPage.master]: uma página que agrupa o que é comum às diferentes visualizações: a barra superior com suas opções de menu
- [Formulaire.aspx]: a página que apresenta o formulário de simulação e gerencia as ações que ocorrem nesse formulário
- [Simulations.aspx]: a página que apresenta a lista de simulações e gerencia as ações realizadas nessa mesma página
- [Erreurs.aspx]: a página exibida quando ocorre um erro de inicialização do aplicativo. Não há ações possíveis nessa página.
Pode-se considerar que temos aqui uma arquitetura MVC com múltiplos controladores, enquanto a arquitetura da versão anterior era uma arquitetura MVC com um único controlador.
O processamento de uma solicitação de um cliente ocorre de acordo com as seguintes etapas:
- o cliente faz uma solicitação à aplicação. Ele a faz em uma das duas páginas [Formulaire.aspx, Simulations.aspx].
- a página solicitada processa essa solicitação. Para isso, ela pode precisar da ajuda da camada [métier], que, por sua vez, pode precisar da camada [dao] caso seja necessário trocar dados com o banco de dados. O aplicativo recebe uma resposta da camada [métier].
- Com base nela, ela seleciona (3) a visualização (= a resposta) a ser enviada ao cliente, fornecendo-lhe (4) as informações (o modelo) de que necessita.
- A resposta é enviada ao cliente (5)
11.1. As visualizações do aplicativo
As diferentes visualizações apresentadas ao usuário são as seguintes:
- - a visualização [VueSaisies], que apresenta o formulário de simulação

- - a visualização [VueSimulation], utilizada para exibir o resultado detalhado da simulação:

- - a visualização [VueSimulations], que exibe a lista das simulações realizadas pelo cliente

- - a visualização [VueSimulationsVides], que indica que o cliente não possui ou não possui mais simulações:

- a visualização [VueErreurs], que indica um erro de inicialização do aplicativo:

11.2. Geração de visualizações em um contexto com vários controladores
Na versão anterior, todas as visualizações eram geradas a partir da única página [Default.aspx]. Essa página continha dois componentes [MultiView], e as visualizações eram compostas pela combinação de um ou dois componentes [View] pertencentes a esses dois componentes [MultiView].
Eficaz quando há poucas visualizações, essa arquitetura atinge seus limites assim que o número de componentes que formam as diferentes visualizações se torna significativo: de fato, a cada solicitação feita à única página [Default.aspx], todos os componentes dessa página são instanciados, embora apenas alguns deles sejam utilizados para gerar a resposta ao usuário. Assim, um trabalho desnecessário é realizado a cada nova solicitação, o que se torna oneroso quando o número total de componentes da página é elevado.
Uma solução é, portanto, distribuir as visualizações por diferentes páginas. É isso que fazemos aqui. Vamos analisar dois casos diferentes de geração de visualizações:
- a solicitação é feita a uma página P1, e esta gera a resposta
- a solicitação é feita a uma página P1 e esta solicita que uma página P2 gere a resposta
11.2.1. Caso 1: uma página controladora/visão
No caso 1, voltamos à arquitetura de controlador único da versão anterior, em que a página [Default.aspx] é a página P1:
![]() |
- o cliente faz uma solicitação à página P1 (1)
- a página P1 processa essa solicitação. Para isso, ela pode precisar da ajuda da camada [métier] (2), que, por sua vez, pode precisar da camada [dao] caso seja necessário trocar dados com o banco de dados. A aplicação recebe uma resposta da camada [métier].
- Com base nela, ela seleciona (3) a visualização (= a resposta) a ser enviada ao cliente, fornecendo-lhe (4) as informações (o modelo) de que necessita. Trata-se, neste caso, de selecionar na página P1 os componentes [Panel] ou [View] a serem exibidos e de inicializar os componentes que eles contêm.
- A resposta é enviada ao cliente (5)
Aqui estão dois exemplos retirados do aplicativo em análise:
[page Formulaire.aspx]
![]() |
- em [1]: o usuário, após ter solicitado a página [Formulaire.aspx], solicita uma simulação
- em [2]: a página [Formulaire.aspx] processou essa solicitação e gerou ela mesma a resposta, exibindo um componente [View] que não havia sido exibido em [1]
[page Simulations.aspx]
![]() |
- em [1]: o usuário, após ter solicitado a página [Simulations.aspx], deseja remover uma simulação
- em [2]: a página [Simulations.aspx] processou essa solicitação e gerou ela mesma a resposta, exibindo novamente a nova lista de simulações.
2 ![]() |
11.2.2. Caso 2: uma página 1 controladora, uma página 2 controladora/visualização
O caso 2 pode abranger diversas arquiteturas. Escolheremos a seguinte:
![]() |
- o cliente faz uma solicitação à página P1 (1)
- a página P1 processa essa solicitação. Para isso, ela pode precisar da ajuda da camada [métier] (2), que, por sua vez, pode precisar da camada [dao] caso seja necessário trocar dados com o banco de dados. A aplicação recebe uma resposta da camada [métier].
- Com base nela, ela seleciona (3) a visualização (= a resposta) a ser enviada ao cliente, fornecendo-lhe (4) as informações (o modelo) de que necessita. Acontece que, neste caso, a visualização a ser gerada deve ser feita por outra página que não a P1, a página P2. Para realizar as operações (3) e (4), a página P1 tem duas possibilidades:
- fazer uma transferência de execução para a página P2 por meio da operação [Server.Transfer(" P2.aspx ")]. Nesse caso, ela pode inserir o modelo destinado à página P2 no contexto da solicitação [Context.Items[" clé "]=valeur] ou na sessão do usuário [Session.[" clé "]=valeur]. A página P2 será então instanciada e, durante o processamento de seu evento Load, por exemplo, ela poderá recuperar as informações transmitidas pela página P1 por meio das operações [valeur=(Type)Context.Items[" clé "]] ou [valeur=(Type)Session[" clé "]], conforme o caso, em que Type é o tipo do valor associado à chave. A transmissão de valores pelo contexto Context é a mais adequada caso não haja necessidade de que os valores do modelo sejam mantidos para uma futura solicitação do cliente.
- solicitar ao cliente que seja redirecionado para a página P2 por meio da operação [Response.Redirect(" P2.aspx ")]. Nesse caso, a página P1 colocará o modelo destinado à página P2 na sessão, pois o contexto de solicitação Context é removido ao final de cada solicitação. No entanto, neste caso, o redirecionamento provocará o término da primeira solicitação do cliente para P1 e o envio de uma segunda solicitação desse mesmo cliente, desta vez para P2. Há duas solicitações sucessivas. Sabemos que a sessão é um dos meios de preservar a “memória” entre as solicitações. Existem outras soluções além da sessão.
- Independentemente da forma como P2 assume o controle, voltamos então ao caso 1: P2 recebeu uma solicitação que irá processar (5) e irá gerar ela mesma a resposta (6, 7). Também é possível imaginar que a página P2, após processar a solicitação, passe o controle para uma página P3, e assim por diante.
Aqui está um exemplo retirado do aplicativo em análise:
![]() |
- para [1]: o usuário que solicitou a página [Formulaire.aspx] pede para ver a lista de simulações
- em [2]: a página [Formulaire.aspx] processa essa solicitação e redireciona o cliente para a página [Simulations.aspx]. É esta última que fornece a resposta ao usuário. Em vez de solicitar que o cliente seja redirecionado, a página [Formulaire.aspx] poderia ter encaminhado a solicitação do cliente para a página [Simulations.aspx]. Nesse caso, na página [2], veríamos a mesma URL que na página [1]. De fato, um navegador sempre exibe a última URL solicitada:
- a ação solicitada na página [1] destina-se à página [Formulaire.aspx]. O navegador realiza uma solicitação para essa página.
- Se a página [Formulaire.aspx] processar a solicitação e, em seguida, a transferir por meio de [Server.Transfer(" Simulations.aspx ")] para a página [Simulations.aspx], permanecemos na mesma solicitação. O navegador exibirá então, em [2], o URL de [Formulaire.aspx], para o qual ocorreu o POST.
- Se a página [Formulaire.aspx] processar a solicitação e, em seguida, redirecioná-la por meio de [Response.Redirect(" Simulations.aspx ")] para a página [Simulations.aspx], o navegador faz então uma segunda solicitação, um GET para [Simulations.aspx]. O navegador exibirá então, em [2], o URL de [Simulations.aspx], para o qual ocorreu o GET. É isso que a captura de tela [2] acima nos mostra.
11.3. O projeto Visual Web Developer da camada [web]
O projeto Visual Web Developer da camada [web] é o seguinte:
![]() |
- em [1], encontramos:
- o arquivo de configuração [Web.config] do aplicativo – é idêntico ao do aplicativo [pam-v4-3tier-nhibernate-multivues-monopage].
- a página [Default.aspx] – limita-se a redirecionar o cliente para a página [Formulaire.aspx]
- a página [Formulaire.aspx], que apresenta ao usuário o formulário de simulação e processa as ações relacionadas a esse formulário
- a página [Simulations.aspx], que apresenta ao usuário a lista de suas simulações e processa as ações relacionadas a essa página
- a página [Erreurs.aspx], que apresenta ao usuário uma página informando sobre um erro ocorrido ao iniciar o aplicativo web.
- Na página [2], são exibidas as referências do projeto.
Voltemos à arquitetura do novo projeto:
![]() |
Em relação ao projeto [pam-v4-3tier-nhibernate-multivues-monopage], apenas as visualizações foram alteradas. Assim, o novo projeto herda alguns dos arquivos desse projeto:
- o arquivo de configuração [Web.config]
- os arquivos DLL referenciados por [pam-dao-nhibernate, pam-metier-dao-nhibernate, Spring.Core, NHibernate]
- a classe global de aplicação [Global.asax]
- as pastas [images, ressources, pam]
Para manter a coerência com o projeto em desenvolvimento, faremos com que o espaço de nomes das visualizações e da classe global de aplicação seja [pam-v7]:
![]() |
11.4. O código de apresentação das páginas
11.4.1. A página mestre [MasterPage.master]
As visualizações da aplicação apresentadas no parágrafo 11.1 possuem partes comuns que podem ser agrupadas em uma página mestre, chamada de Master Page no Visual Studio. Tomemos, por exemplo, as visualizações [VueSaisies] e [VueSimulationsVides] abaixo, geradas respectivamente pelas páginas [Formulaire.aspx] e [Simulations.aspx]:
![]() |
Essas duas visualizações têm em comum a barra superior (Título e Opções de menu). O mesmo se aplica a todas as visualizações que serão apresentadas ao usuário: todas terão a mesma barra superior. Para que diferentes páginas compartilhem um mesmo fragmento de apresentação, existem diversas soluções, entre as quais as seguintes:
- colocar esse fragmento comum em um componente de usuário. Essa era a principal técnica utilizada no ASP.NET 1.1
- colocar esse fragmento comum em uma página mestre. Essa técnica surgiu com o ASP.NET 2.0. É a que estamos utilizando aqui.
Para criar uma página mestre em um aplicativo web, pode-se proceder da seguinte forma:
- clique com o botão direito do mouse no projeto / Adicionar um novo elemento / Página mestre:
![]() |
A adição de uma página mestre insere, por padrão, três arquivos na aplicação web:
- [MasterPage.master]: o código de apresentação da página mestre
- [MasterPage.master.cs]: o código de controle da página mestre
- [Masterpage.Master.designer.cs]: a declaração dos componentes da página mestre
O código gerado pelo Visual Studio no arquivo [MasterPage.master] é o seguinte:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MasterPage.master.cs" Inherits="pam_v7.MasterPage" %>
<!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 runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
- linha 1: a tag <%@ Master ... %> serve para definir a página como uma página mestre. O código de controle da página estará no arquivo definido pelo atributo CodeBehind, e a página herdará a classe definida pelo atributo Inherits.
- linhas 12-18: o formulário da página mestre
- linhas 14-16: um contêiner vazio que, em nossa aplicação, conterá uma das páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]. O cliente recebe como resposta, sempre a mesma página, a página mestre, na qual o contêiner [ContentPlaceHolder1] receberá um fluxo HTML fornecido por uma das páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]. Assim, para alterar a aparência das páginas enviadas aos clientes, basta alterar a aparência da página mestre.
- linhas 8-9: um contêiner vazio com o qual as páginas “filhas” poderão personalizar o cabeçalho <head>...</head>.
A representação visual (aba Design) desse código-fonte é apresentada em (1) abaixo. Além disso, é possível adicionar quantos contêineres forem desejados, graças ao componente [ContentPlaceHolder] (2) da barra de ferramentas [Standard].
![]() |
O código de controle gerado pelo Visual Studio no [MasterPage.master.cs] é o seguinte:
using System;
public partial class MasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
- linha 3: a classe referenciada pelo atributo [Inherits] da diretiva <%@ Master ... %> da página [MasterPage.master] deriva da classe [System.Web.UI.MasterPage]
Acima, vemos a presença do método Page_Load, que gerencia o evento Load da página mestre. A página mestre conterá, em seu interior, outra página. Em que ordem ocorrem os eventos Load das duas páginas? Trata-se de uma regra geral: o evento Load de um componente ocorre antes do evento de seu contêiner. Nesse caso, o evento Load da página inserida na página mestre ocorrerá, portanto, antes do evento da própria página mestre.
Para que gere uma página cuja página-mestre seja a página [MasterPage.master] anterior, pode-se proceder da seguinte forma:
![]() |
- em [1]: clique com o botão direito do mouse na página mestre e selecione a opção [Ajouter une page de contenu]
- em [2]: é gerada uma página padrão, neste caso [WebForm1.aspx].
O código de apresentação [WebForm1.aspx] é o seguinte:
<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="pam_v7.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
- linha 1: a diretiva Page e seus atributos
- MasterPageFile: indica o arquivo da página-mestre da página descrita pela diretiva. O sinal ~ indica a pasta do projeto.
- os demais parâmetros são os habituais de uma página da web ASP
- linhas 2-3: as tags <asp:Content> são vinculadas, uma a uma, às diretivas <asp:ContentPlaceHolder> da página mestre por meio do atributo ContentPlaceHolderID. Os componentes colocados entre as linhas 2 e 3 acima serão, na execução, inseridos no contêiner de ID ContentPlaceHolder1 da página mestre.
Ao renomear a página [WebForm1.aspx] assim gerada, é possível criar as diferentes páginas tendo [MasterPage.master] como página mestre.
Para nossa aplicação [SimuPaie], a aparência da página-mestre será a seguinte:
![]() |
N.º | Tipo | Nome | Função |
Painel (rosa acima) | cabeçalho | cabeçalho da página | |
Painel (amarelo acima) | conteúdo | conteúdo da página | |
LinkButton | LinkButtonFaireSimulation | solicita o cálculo da simulação | |
LinkButton | LinkButtonEffacerSimulation | apaga o formulário de preenchimento | |
LinkButton | LinkButtonVoirSimulations | exibe a lista das simulações já realizadas | |
LinkButton | LinkButtonFormulaireSimulation | retorna ao formulário de preenchimento | |
LinkButton | LinkButtonEnregistrerSimulation | grava a simulação atual na lista de simulações | |
LinkButton | LinkButtonTerminerSession | encerra a sessão atual |
O código-fonte correspondente é o seguinte:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MasterPage.master.cs" Inherits="pam_v7.MasterPage" %>
<!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>Application PAM</title>
</head>
<body background="ressources/standard.jpg">
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
<asp:UpdatePanel runat="server" ID="UpdatePanelPam" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="entete" runat="server" BackColor="#FFE0C0">
<table>
<tr>
<td>
<h2>
Simulateur de calcul de paie</h2>
</td>
<td>
<label>
 </label>
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img alt="" src="images/indicator.gif" />
<asp:Label ID="Label5" runat="server" BackColor="#FF8000"
EnableViewState="False" Text="Calcul en cours. Patientez ....">
</asp:Label>
</ProgressTemplate>
</asp:UpdateProgress>
</td>
<td>
<asp:LinkButton ID="LinkButtonFaireSimulation" runat="server"
CausesValidation="False">| Faire la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonEffacerSimulation" runat="server"
CausesValidation="False">| Effacer la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonVoirSimulations" runat="server"
CausesValidation="False">| Voir les simulations<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonFormulaireSimulation" runat="server"
CausesValidation="False">| Retour au formulaire de simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonEnregistrerSimulation" runat="server"
CausesValidation="False">| Enregistrer la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonTerminerSession" runat="server"
CausesValidation="False">| Terminer la session<br />
</asp:LinkButton>
</td>
</tr>
</table>
<hr />
</asp:Panel>
<div>
<asp:Panel ID="contenu" runat="server" BackColor="#FFFFC0">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</asp:Panel>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
- linha 1: observe o nome da classe da página mestre: MasterPage
- linha 8: define-se uma imagem de fundo para a página.
- linhas 9-64: o formulário
- linha 10: o componente ScriptManager necessário para os efeitos Ajax
- linhas 11-63: o contêiner AJax
- linhas 12-62: o conteúdo com Ajax
- linhas 13-55: o componente Panel [entete]
- linhas 57-60: o componente Panel [contenu]
- linhas 58-59: o componente ID [ContentPlaceHolder1], que conterá a página encapsulada [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]
Para construir essa página, será possível inserir no painel [entete], o código ASPX da visualização [VueEntete] da página [Default.aspx] da versão [pam-v4-3tier-nhibernate-multivues-monopage], descrita no parágrafo 8.5.2.
11.4.2. A página [Formulaire.aspx]
Para gerar esta página, seguirá-se o método exposto no parágrafo 11.4.1 e renomear-se-á a página [WebForm1.aspx], assim gerada, para [Formulaire.aspx]. A aparência visual da página [Formulaire.aspx] em fase de construção será a seguinte:
![]() |
A aparência da página [Formulaire.aspx] possui dois elementos:
- em [1], a página mestre com seu contêiner [ContentPlaceHolder1] (2)
- em [2], os componentes colocados no contêiner [ContentPlaceHolder1]. Estes são idênticos aos da aplicação anterior.
O código-fonte desta página é o seguinte:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Formulaire.aspx.cs" Inherits="pam_v7.PageFormulaire" Title="Simulation de calcul de paie : formulaire" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<div>
<table>
<tr>
<td>
Employé
</td>
<td>
Heures travaillées
</td>
<td>
Jours travaillés
</td>
<td>
</td>
</tr>
...
</asp:Content>
- linha 1: a diretiva Page com seu atributo MasterPageFile
- linha 4: a classe de controle da página mestre pode expor campos e propriedades públicos. Estes são acessíveis às páginas encapsuladas com a sintaxe Master.[champ] ou Master.[propriété]. A propriedade Master da página designa a página mestre na forma de uma instância do tipo [System.Web.UI.MasterPage]. Portanto, em nosso exemplo, seria necessário escrever, na verdade, (MasterPage)(Master).[champ] ou (MasterPage)(Master).[propriété]. É possível evitar essa conversão de tipo inserindo na página a diretiva MasterType da linha 4. O atributo VirtualPath dessa diretiva indica o arquivo da página mestre. O compilador pode, então, identificar os campos, propriedades e métodos públicos expostos pela classe da página mestre, neste caso do tipo [MasterPage].
- linhas 5-22: o conteúdo que será inserido no contêiner [ContentPlaceHolder1] da página mestre.
É possível construir essa página inserindo como conteúdo (linhas 6-21) o da visualização [VueSaisies] descrita no parágrafo 8.5.3 e o da visualização [VueSimulation] descrita no parágrafo 8.5.4.
11.4.3. A página [Simulations.aspx]
Para gerar esta página, seguirá-se o método exposto no parágrafo 11.4.1 e renomeará-se a página [WebForm1.aspx], assim gerada, para [Simulations.aspx]. A aparência visual da página [Simulations.aspx] em fase de construção é a seguinte:
![]() |
A aparência visual da página [Simulations.aspx] possui dois elementos:
- em [1], a página mestre com seu contêiner [ContentPlaceHolder1]
- em [2], os componentes colocados no contêiner [ContentPlaceHolder1]. Estes são idênticos aos da aplicação anterior.
O código-fonte desta página é o seguinte:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Simulations.aspx.cs" Inherits="pam_v7.PageSimulations" Title="Pam : liste des simulations" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:MultiView ID="MultiView1" runat="server">
<asp:View ID="View1" runat="server">
<h2>
Liste de vos simulations</h2>
<p>
<asp:GridView ID="GridViewSimulations" runat="server" ...>
...
</asp:GridView>
</p>
</asp:View>
<asp:View ID="View2" runat="server">
<h2>
La liste de vos simulations est vide</h2>
</asp:View>
</asp:MultiView><br />
</asp:Content>
É possível construir essa página inserindo como conteúdo (linhas 5-21) o da visualização [VueSimulations] descrita no parágrafo 8.5.5 e o da visualização [VueSimulationsVides] descrita no parágrafo 8.5.6.
11.4.4. A página [Erreurs.aspx]
Para gerar esta página, seguirá-se o método exposto no parágrafo 11.4.1 e renomeará-se a página [WebForm1.aspx], assim gerada, para [Erreurs.aspx]. A aparência visual da página [Erreurs.aspx] em fase de construção é a seguinte:
![]() |
A aparência visual da página [Erreurs.aspx] possui dois elementos:
- em [1], a página mestre com seu contêiner [ContentPlaceHolder1]
- em [2], os componentes colocados no contêiner [ContentPlaceHolder1]. Estes são idênticos aos da aplicação anterior.
O código-fonte desta página é o seguinte:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Erreurs.aspx.cs" Inherits="pam_v7.PageErreurs" Title="Pam : erreurs" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<h3>Les erreurs suivantes se sont produites au démarrage de l'application</h3>
<ul>
<asp:Repeater id="rptErreurs" runat="server">
<ItemTemplate>
<li>
<%# Container.DataItem %>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</asp:Content>
11.5. O código de controle das páginas
11.5.1. Visão geral
Voltemos à arquitetura do aplicativo:
![]() |
- [Global] é o objeto do tipo [HttpApplication] que inicializa (etapa 0) o aplicativo. Essa classe é idêntica à da versão anterior.
- O código do controlador, que na versão anterior estava inteiramente em [Default.aspx.cs], agora está distribuído por várias páginas:
- [MasterPage.master]: a página mestre das páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]. Ela contém o menu.
- [Formulaire.aspx]: a página que apresenta o formulário de simulação e gerencia as ações realizadas nesse formulário
- [Simulations.aspx]: a página que exibe a lista de simulações e gerencia as ações realizadas nessa mesma página
- [Erreurs.aspx]: a página exibida quando ocorre um erro de inicialização do aplicativo. Não há ações possíveis nessa página.
O processamento de uma solicitação de um cliente ocorre de acordo com as seguintes etapas:
- o cliente faz uma solicitação ao aplicativo. Normalmente, ele a faz em uma das duas páginas [Formulaire.aspx, Simulations.aspx], mas nada o impede de solicitar a página [Erreurs.aspx]. É preciso prever esse caso.
- a página solicitada processa essa solicitação (etapa 1). Para isso, ela pode precisar da ajuda da camada [métier] (etapa 2), que, por sua vez, pode precisar da camada [dao] caso seja necessário trocar dados com o banco de dados. A aplicação recebe uma resposta da camada [métier].
- Com base nela, ela escolhe (etapa 3) a visualização (= a resposta) a ser enviada ao cliente e fornece a ele (etapa 4) as informações (o modelo) de que precisa. Vimos três possibilidades para gerar essa resposta:
- a página (D) solicitada é também a página (R) enviada como resposta. Construir o modelo da resposta (R) consiste, então, em atribuir a alguns dos componentes da página (D) o valor que eles devem ter na resposta.
- a página (D) solicitada não é a página (R) enviada como resposta. A página (D) pode então:
- transferir o fluxo de execução para a página (R) por meio da instrução Server.Transfer(" R "). O modelo pode então ser inserido no contexto por meio da instrução Context.Items("chave")=valor ou, mais raramente, na sessão por meio da instrução Session.Items("chave")=valor
- redirecionar o cliente para a página (R) por meio da instrução Response.redirect(" R "). O modelo pode então ser inserido na sessão, mas não no contexto.
- A resposta é enviada ao cliente (etapa 5)
Cada uma das páginas [MasterPage.master, Formulaire.aspx, Simulations.aspx, Erreurs.aspx] responderá a um ou mais dos eventos abaixo:
- Init: primeiro evento no ciclo de vida da página
- Load: ocorre ao carregar a página
- Click: o clique em um dos links do menu da página mestre
Processamos as páginas uma após a outra, começando pela página principal.
11.5.2. Código de controle da página [MasterPage.master]
11.5.2.1. Estrutura da classe
O código de controle da página mestre tem a seguinte estrutura:
using System.Web.UI.WebControls;
namespace pam_v7
{
public partial class MasterPage : System.Web.UI.MasterPage
{
// o menu
public LinkButton OptionFaireSimulation
{
get { return LinkButtonFaireSimulation; }
}
...
// fixar o menu
public void SetMenu(bool boolFaireSimulation, bool boolEnregistrerSimulation, bool boolEffacerSimulation, bool boolFormulaireSimulation, bool boolVoirSimulations, bool boolTerminerSession)
{
....
}
// gerenciamento da opção [Terminer la session]
protected void LinkButtonTerminerSession_Click(object sender, System.EventArgs e)
{
....
}
// inicializar a página mestre
protected void Page_Init(object sender, System.EventArgs e)
{
....
}
}
}
}
- linha 5: a classe se chama [MasterPage] e deriva da classe do sistema [System.Web.UI.MasterPage].
- linhas 9-14: as seis opções do menu são definidas como propriedades públicas da classe
- linhas 16-19: o método público SetMenu permitirá que as páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] definam o menu da página mestre
- linhas 22-25: o procedimento que irá gerenciar o clique no link [LinkButtonTerminerSession]
- linhas 28-31: o procedimento de gerenciamento do evento Init da página mestre
11.5.2.2. Propriedades públicas da classe
using System.Web.UI.WebControls;
namespace pam_v7
{
public partial class MasterPage : System.Web.UI.MasterPage
{
// o menu
public LinkButton OptionFaireSimulation
{
get { return LinkButtonFaireSimulation; }
}
public LinkButton OptionEffacerSimulation
{
get { return LinkButtonEffacerSimulation; }
}
public LinkButton OptionEnregistrerSimulation
{
get { return LinkButtonEnregistrerSimulation; }
}
public LinkButton OptionVoirSimulations
{
get { return LinkButtonVoirSimulations; }
}
public LinkButton OptionTerminerSession
{
get { return LinkButtonTerminerSession; }
}
public LinkButton OptionFormulaireSimulation
{
get { return LinkButtonFormulaireSimulation; }
}
...
}
}
Para entender esse código, é preciso lembrar os componentes que formam a página mestre:
![]() |
N.º | Tipo | Nome | Função |
Painel (rosa acima) | cabeçalho | cabeçalho da página | |
Painel (amarelo acima) | conteúdo | conteúdo da página | |
LinkButton | LinkButtonFaireSimulation | solicita o cálculo da simulação | |
LinkButton | LinkButtonEffacerSimulation | apaga o formulário de preenchimento | |
LinkButton | LinkButtonVoirSimulations | exibe a lista das simulações já realizadas | |
LinkButton | LinkButtonFormulaireSimulation | retorna ao formulário de preenchimento | |
LinkButton | LinkButtonEnregistrerSimulation | grava a simulação atual na lista de simulações | |
LinkButton | LinkButtonTerminerSession | encerra a sessão atual |
Os componentes 1 a 6 não são acessíveis fora da página que os contém. As propriedades das linhas 9 a 37 têm como objetivo torná-los acessíveis a classes externas, neste caso, as classes das outras páginas do aplicativo.
11.5.2.3. O método SetMenu
O método público SetMenu permite que as páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] definam o menu da página mestre. Seu código é básico:
// fixar o menu
public void SetMenu(bool boolFaireSimulation, bool boolEnregistrerSimulation, bool boolEffacerSimulation, bool boolFormulaireSimulation, bool boolVoirSimulations, bool boolTerminerSession)
{
// definindo as opções do menu
LinkButtonFaireSimulation.Visible = boolFaireSimulation;
LinkButtonEnregistrerSimulation.Visible = boolEnregistrerSimulation;
LinkButtonEffacerSimulation.Visible = boolEffacerSimulation;
LinkButtonVoirSimulations.Visible = boolVoirSimulations;
LinkButtonFormulaireSimulation.Visible = boolFormulaireSimulation;
LinkButtonTerminerSession.Visible = boolTerminerSession;
}
11.5.2.4. Gerenciamento de eventos da página mestre
A página mestre irá gerenciar dois eventos:
- o evento Init, que é o primeiro evento do ciclo de vida da página
- o evento Click no link [LinkButtonTerminerSession]
A página mestre possui outros cinco links: [LinkButtonFaireSimulation, LinkButtonEnregistrerSimulation, LinkButtonEffacerSimulation, LinkButtonVoirSimulations, LinkButtonFormulaireSimulation]. A título de exemplo, vamos examinar o que seria necessário fazer ao clicar no link [LinkButtonFaireSimulation]:
- verificar os dados inseridos (horas, dias) na página [Formulaire.aspx]
- fazer o cálculo do salário
- exibir os resultados na página [Formulaire.aspx]
As operações 1 e 3 exigem acesso aos componentes da página [Formulaire.aspx]. Esse não é o caso. De fato, a página mestre não tem conhecimento dos componentes das páginas que podem ser inseridas em seu contêiner [ContentPlaceHolder1]. No nosso exemplo, cabe à página [Formulaire.aspx] gerenciar o clique no link [LinkButtonFaireSimulation], pois é ela que está sendo exibida quando esse evento ocorre. Como ela pode ser notificada sobre esse evento?
- Como o link [LinkButtonFaireSimulation] não faz parte da página [Formulaire.aspx], não é possível escrever na página [Formulaire.aspx] o procedimento habitual:
private void LinkButtonFaireSimulation_Click(object sender, System.EventArgs e)
{
...
}
É possível contornar o problema com o seguinte código em [Formulaire.aspx]:
using System.Collections.Generic;
...
namespace pam_v7
{
public partial class Formulaire : System.Web.UI.Page
{
// carregamento da página
protected void Page_Load(object sender, System.EventArgs e)
{
// gerenciador de eventos
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
...
}
// cálculo da folha de pagamento
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
....
}
// apagar a simulação
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
...
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
...
}
}
}
- linhas 12-15: quando ocorre o evento Load da página [Formulaire.aspx], a classe [MasterPage] da página mestre já foi instanciada. Suas propriedades públicas Optionxx estão acessíveis e são do tipo LinkButton, um componente que suporta o evento Click. Associamos a esses eventos Click os métodos:
- OptFaireSimulation_Click para o evento Click no link LinkButtonFaireSimulation
- OptEffacerSimulation_Click para o evento Click no link LinkButtonEffacerSimulation
- OptVoirSimulations_Click para o evento Click no link LinkButtonVoirSimulations
- OptEnregistrerSimulation_Click para o evento Click no link LinkButtonEnregistrerSimulation
O gerenciamento dos eventos Click nos seis links do menu será distribuído da seguinte forma:
- a página [Formulaire.aspx] gerenciará os links [LinkButtonFaireSimulation, LinkButtonEnregistrerSimulation, LinkButtonEffacerSimulation, LinkButtonVoirSimulations]
- a página [Simulations.aspx] gerenciará o link [LinkButtonFormulaireSimulation]
- a página mestre [MasterPage.master] administrará o link [LinkButtonTerminerSession]. Para esse evento, ela não precisa saber qual é a página que está encapsulando.
11.5.2.5. O evento Init da página mestre
As três páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] do aplicativo têm [MasterPage.master] como página mestre. Chamemos de M a página mestre e de E a página encapsulada. Quando a página E é solicitada pelo cliente, os seguintes eventos ocorrem na seguinte ordem:
- E.Init
- M.Init
- E.Load
- M.Load
- ...
Vamos utilizar o evento Init da página M para executar um código que seria interessante executar o mais cedo possível, independentemente da página de destino E. Para identificar esse código, vamos revisar a visão geral do aplicativo:
![]() |
Acima, [Global] é o objeto do tipo [HttpApplication] que inicializa a aplicação. Essa classe é a mesma da versão [pam-v4-3tier-nhibernate-multivues-monopage]:
using System;
...
namespace pam_v7
{
public class Global : System.Web.HttpApplication
{
// --- dados estáticos do aplicativo ---
public static Employe[] Employes;
public static IPamMetier PamMetier = null;
public static string Msg;
public static bool Erreur = false;
// inicialização do aplicativo
public void Application_Start(object sender, EventArgs e)
{
...
}
public void Session_Start(object sender, EventArgs e)
{
...
}
}
}
Se a classe [Global] não conseguir inicializar corretamente o aplicativo, ela define duas variáveis públicas estáticas:
- a variável booleana Erro, na linha 12, é definida como vrai
- a variável `Msg` da linha 11 contém uma mensagem com detalhes sobre o erro ocorrido
Quando o usuário solicita uma das páginas [Formulaire.aspx, Simulations.aspx], mas o aplicativo não foi inicializado corretamente, essa solicitação deve ser transferida ou redirecionada para a página [Erreurs.aspx], que exibirá a mensagem de erro da classe [Global]. É possível lidar com esse caso de várias maneiras:
- realizar o teste de erro de inicialização no gerenciador de eventos Init ou Load de cada uma das páginas [Formulaire.aspx, Simulations.aspx]
- executar o teste de erro de inicialização no gerenciador de eventos Init ou Load da página mestre dessas duas páginas. Esse método tem a vantagem de centralizar o teste de erro de inicialização em um único local.
Optamos por realizar o teste de erro de inicialização no gerenciador de eventos Init da página mestre:
protected void Page_Init(object sender, System.EventArgs e)
{
// gerenciador de eventos
LinkButtonTerminerSession.Click += LinkButtonTerminerSession_Click;
// erros de inicialização?
if (Global.Erreur)
{
// a página encapsulada é a página de erros?
bool isPageErreurs =...;
// se for a página de erros que estiver sendo exibida, deixamos como está; caso contrário, redirecionamos o cliente para a página de erros
if (!isPageErreurs)
Response.Redirect("Erreurs.aspx");
return;
}
}
O código acima será executado assim que uma das páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] for solicitada. Caso a página solicitada seja [Formulaire.aspx, Simulations.aspx], basta (linha 12) redirecionar o cliente para a página [Erreurs.aspx], que se encarregará de exibir a mensagem de erro da classe [Global]. Caso a página solicitada seja [Erreurs.aspx], esse redirecionamento não deve ocorrer: é preciso permitir que a página [Erreurs.aspx] seja exibida. Portanto, precisamos saber, no método [Page_Init] da página mestre, qual é a página que ela encapsula.
Voltemos à árvore de componentes da página mestre:
...
<body background="ressources/standard.jpg">
<form id="form1" runat="server">
<asp:Panel ID="entete" runat="server" BackColor="#FFE0C0" Width="1239px" >
...
</asp:Panel>
<div>
<asp:Panel ID="contenu" runat="server" BackColor="#FFFFC0">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</asp:Panel>
</div>
</form>
</body>
</html>
- linhas 1-13: o contêiner com id “form1”
- linhas 4-6: o contêiner com o id “entete”, incluído no contêiner com o id “form1”
- linhas 8-11: o contêiner com o id “contenu”, incluído no contêiner com o id “form1”
- linhas 9-10: o contêiner com o id “ContentPlaceHolder1”, incluído no contêiner com o id “contenu”
Uma página E encapsulada na página mestre M está contida no contêiner com o ID “ContentPlaceHolder1”. Para referenciar um componente com o ID C dessa página E, escrever-se-á:
this.FindControl("form1").FindControl("contenu").FindControl("ContentPlaceHolder1").FindControl("C");
A árvore de componentes da página [Erreurs.aspx] é a seguinte:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Erreurs.aspx.cs" Inherits="pam_v7.PageErreurs" Title="Pam : erreurs" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<h3>Les erreurs suivantes se sont produites au démarrage de l'application</h3>
<ul>
<asp:Repeater id="rptErreurs" runat="server">
<ItemTemplate>
<li>
<%# Container.DataItem %>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</asp:Content>
Quando a página [Erreurs.aspx] é mesclada com a página mestre M, o conteúdo da tag <asp:Content> acima (linhas 5-16) é integrado à tag <asp:ContentPlaceHolder> com id “ContentPlaceholder1” da página M, ficando sua árvore de componentes da seguinte forma:
- linha 12: o componente [rptErreurs] pode ser usado para verificar se a página mestre M contém ou não a página [Erreurs.aspx]. De fato, esse componente existe apenas nessa página.
Essas explicações são suficientes para compreender o código do procedimento [Page_Init] da página mestre:
protected void Page_Init(object sender, System.EventArgs e)
{
// gerenciador de eventos
LinkButtonTerminerSession.Click += LinkButtonTerminerSession_Click;
// erros de inicialização?
if (Global.Erreur)
{
// a página encapsulada é a página de erros?
bool isPageErreurs = this.FindControl("form1").FindControl("contenu").FindControl("ContentPlaceHolder1").FindControl("rptErreurs") != null;
// se for a página de erros que estiver sendo exibida, deixamos como está; caso contrário, redirecionamos o cliente para a página de erros
if (!isPageErreurs)
Response.Redirect("Erreurs.aspx");
return;
}
}
- linha 4: associa-se um manipulador de evento ao evento Click no link LinkButtonTerminerSession. Esse manipulador está na classe MasterPage.
- linha 6: verifica-se se a classe [Global] definiu seu valor booleano Erreur
- linha 9: se sim, o booleano IsPageErreurs indica se a página encapsulada na página mestre é a página [Erreurs.aspx]
- linha 12: se a página encapsulada na página mestre não for a página [Erreurs.aspx], então o cliente é redirecionado para essa página; caso contrário, nada é feito.
11.5.2.6. O evento Click no link [LinkButtonTerminerSession]
![]() |
Quando o usuário clica no link [Terminer la session] na visualização (1) acima, é necessário esvaziar o conteúdo da sessão e apresentar um formulário vazio (2).
O código do manipulador desse evento poderia ser o seguinte:
protected void LinkButtonTerminerSession_Click(object sender, System.EventArgs e)
{
// a sessão é encerrada
Session.Abandon();
// exibe-se a visualização [formulaire]
Response.Redirect("Formulaire.aspx");
}
- linha 4: a sessão atual é encerrada
- linha 6: o cliente é redirecionado para a página [Formulaire.aspx]
Percebe-se que esse código não envolve nenhum dos componentes das páginas [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]. O evento pode, portanto, ser gerenciado pela própria página mestre.
11.5.3. Código de controle da página [Erreurs.aspx]
O código de controle da página [Erreurs.aspx] poderia ser o seguinte:
using System.Collections.Generic;
namespace pam_v7
{
public partial class Erreurs : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
// erros de inicialização?
if (Global.Erreur)
{
// prepara-se o modelo da página [erreurs]
List<string> erreursInitialisation = new List<string>();
erreursInitialisation.Add(Global.Msg);
// associa-se a lista de erros ao respectivo componente
rptErreurs.DataSource = erreursInitialisation;
rptErreurs.DataBind();
}
// definindo o menu
Master.SetMenu(false, false, false, false, false, false);
}
}
}
Vale lembrar que a página [Erreurs.aspx] tem como única função exibir um erro de inicialização do aplicativo quando este ocorre:
- linha 10: verifica-se se a inicialização terminou com um erro
- linhas 13-14: se sim, a mensagem de erro (Global.Msg) é inserida em uma lista [ErreursInitialisation]
- linhas 16-17: solicita-se ao componente [rptErreurs] que exiba essa lista
- linha 20: em todos os casos (com ou sem erro), as opções do menu da página mestre não são exibidas, de modo que o usuário não pode iniciar nenhuma nova ação a partir dessa página.
O que acontece se o usuário acessar diretamente a página [Erreurs.aspx] (o que não deve ocorrer no uso normal do aplicativo)? Ao analisar o código das páginas [MasterPage.master.cs] e [Erreurs.aspx.cs], percebe-se que:
- se houver um erro de inicialização, ele é exibido
- se não houver erro de inicialização, o usuário recebe uma página contendo apenas o cabeçalho de [MasterPage.master], sem nenhuma opção de menu exibida.
11.5.4. Código de controle da página [Formulaire.aspx]
11.5.4.1. Estrutura da classe
A estrutura do código de controle da página [Formulaire.aspx] poderia ser a seguinte:
using Pam.Metier.Entites;
...
partial class PageFormulaire : System.Web.UI.Page
{
// carregamento da página
protected void Page_Load(object sender, System.EventArgs e)
{
// gerenciador de eventos
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
....
}
// cálculo da folha de pagamento
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
....
}
// apagar a simulação
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
....
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
...
}
}
O código de controle da página [Formulaire.aspx] gerencia cinco eventos:
- o evento Load da página
- o evento Click no link [LinkButtonFaireSimulation] da página mestre
- o evento Click no link [LinkButtonEffacerSimulation] da página mestre
- o evento Click no link [LinkButtonEnregistrerSimulation] da página mestre
- o evento Click no link [LinkButtonVoirSimulations] da página mestre
11.5.4.2. Evento de carregamento da página
O esboço do gerenciador do evento Load da página poderia ser o seguinte:
protected void Page_Load(object sender, System.EventArgs e)
{
// gerenciador de eventos
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
// exibição da visualização [saisies]
...
// posicionamento do menu da página mestre
...
// processamento de consulta GET
if (!IsPostBack)
{
// carregamento dos nomes dos funcionários na lista suspensa
...
// inicialização da visualização [saisies] com os dados inseridos armazenados na sessão, caso existam
....
}
}
Um exemplo para esclarecer o comentário da linha 17 poderia ser este:
![]() |
![]() |
- em [1], solicita-se a exibição da lista de simulações. Foram feitas entradas em [A, B, C].
- em [2], é exibida a lista
- em [3], solicita-se o retorno ao formulário
- em [4], o formulário é exibido exatamente como foi deixado. Como houve duas solicitações, (1,2) e (3,4), isso significa que:
- ao passar de [1] para [2], os dados inseridos em [1] foram armazenados
- ao passar de [3] para [4], elas foram restauradas. É o procedimento [Page_Load] de [Formulaire.aspx] que realiza essa restauração.
Pergunta: complete o procedimento Page_Load com a ajuda dos comentários e do código da versão [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.4.3. Gerenciamento de eventos de clique nos links do menu
A estrutura dos gerenciadores de eventos Click para os links da página principal é a seguinte:
// cálculo da folha de pagamento
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
// efeito Ajax
Thread.Sleep(3000);
// página válida?
Page.Validate();
if (!Page.IsValid)
{
// exibição da visualização [saisie]
...
}
// a página é válida — recuperamos os dados inseridos
...
// calcula-se o salário do funcionário
FeuilleSalaire feuillesalaire;
try
{
feuillesalaire = ...;
}
catch (PamException ex)
{
// ocorreu um problema
...
return;
}
// o resultado é armazenado na sessão
Session["simulation"] = ...;
// as entradas são armazenadas na sessão
...
// exibição
...
// exibição de visualizações
...
// exibição do menu MasterPage
...
}
// apagar a simulação
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
// exibição do painel [saisie]
...
// seleção do primeiro funcionário
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
// insere-se as entradas na sessão
...
// exibe-se a visualização [simulations]
Response.Redirect("simulations.aspx");
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
// salva-se a simulação atual na sessão do usuário
...
// exibe-se a visualização [simulations]
Response.Redirect("simulations.aspx");
}
Pergunta: complete o código dos procedimentos acima com a ajuda dos comentários e do código da versão [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.5. Código de controle da página [Simulations.aspx]
A estrutura do código de controle da página [Simulations.aspx] poderia ser a seguinte:
using System.Collections.Generic;
using Pam.Web;
using System.Web.UI.WebControls;
partial class PageSimulations : System.Web.UI.Page
{
// as simulações
private List<Simulation> simulations;
// carregamento da página
protected void Page_Load(object sender, System.EventArgs e)
{
// gerenciador de eventos
Master.OptionFormulaireSimulation.Click += OptFormulaireSimulation_Click;
GridViewSimulations.RowDeleting += GridViewSimulations_RowDeleting;
// recuperando as simulações da sessão
simulations = ...;
// há simulações?
if (simulations.Count != 0)
{
// primeira visualização exibida
...
// preenchimento do GridView
...
}
else
{
// segunda visualização
...
}
// definindo o menu
...
}
protected void GridViewSimulations_RowDeleting(object sender, System.Web.UI.WebControls.GridViewDeleteEventArgs e)
{
// recuperando as simulações na sessão
List<Simulation> simulations = ...;
// exclui-se a simulação indicada (e.RowIndex representa o número da linha excluída no GridView)
..
// Ainda há simulações?
if (simulations.Count != 0)
{
// preenche-se a visualização em grade
...
}
else
{
// visualização [SimulationsVides]
...
}
}
protected void OptFormulaireSimulation_Click(object sender, System.EventArgs e)
{
// exibe-se a visualização [formulaire]
Response.Redirect("formulaire.aspx");
}
}
Pergunta: complete o código dos procedimentos acima com a ajuda dos comentários e do código da versão [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.6. Código de controle da página [Default.aspx]
É possível prever uma página [Default.aspx] no aplicativo, a fim de permitir que o usuário solicite o URL do aplicativo sem especificar uma página, conforme mostrado abaixo:
![]() |
A solicitação [1] recebeu como resposta a página [Formulaire.aspx] (2). Sabe-se que a solicitação (1) é processada, por padrão, pela página [Default.aspx] do aplicativo. Para obter (2), basta que [Default.aspx] redirecione o cliente para a página [Formulaire.aspx]. Isso pode ser feito com o seguinte código:
partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, System.EventArgs e)
{
// redireciona para o formulário de preenchimento
Response.Redirect("Formulaire.aspx");
}
}
A página de apresentação [Default.aspx] contém apenas a diretiva que a vincula à [Default.aspx.cs]:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="pam_v7._Default" Title="Untitled Page" %>

























