21 de set. de 2009

Themes, Skins & Master Page in ASP.NET

Antes de começar:

O exemplo foi projetado no Visual Studio 2008 e compilado no .NET framework 3.5.

Usamos uma herança da Classe Page do framework, para assim, poder sobrescrever o método Pre_Render(), podendo assim, atribuir uma skin ao site, aproveitando o recurso da Master Page.

A pouca codificação é uma credibilidade, apesar de certo espanto de alguns, como diriam: Se esta complicado no .NET é porquê você está fazendo errado!

Introdução:

As aplicações web, sites, portais, blogs etc... estão cada vês mais dinâmicos com conteúdo variado e uma rica mídia a disposição, assim como uma flexibilidade enorme de apresentação deste conteúdo.

O desenvolvedor web se flagra em muitas ciladas para desenvolver interfaces de usuários flexíveis, dinâmicas... e por que não “mutantes”!?

Já pararam para usar os temas e skins do ASP.NET, principalmente com Master Pages?

O ASP.NET dispõe destes recursos que dão ao desenvolvedor o poder para trazer flexibilidade e dinâmica do desing do seu projeto web sem sofrer muito com codificação ou repetição de códigos, economizando tempo e trazendo funcionalidades diversas à aplicação.

Isto também nos remete aos modelos de camadas onde há uma separação de funcionalidades e múltiplas interfaces de usuário. Utilizando estes recursos, nós separamos metodicamente as interfaces de usuário das funcionalidades.

Procurei reunir as informações primordiais para implementar um site e/ou aplicação web com uma interface rica e dinâmica no frontend , usufruindo deste simples recurso que o ASP.NET dispõe, criando assim “templates” para o seu site/aplicação.

Criando Projeto:

Crie um novo projeto ASP.NET Web Application ou simplesmente siga os próximos passos para implementar esta funcionalidade em uma aplicação e/ou website existente.

image

Adicionando a Mater Page:

Se você não sabe o que é uma Master Page¸ no ASP.NET, é uma alternativa inteligente ao “iframe” do HTML. Basicamente ele define a estrutura básica do seu site, deixando o espaço definido aonde os conteúdos serão inseridos (ContentPlaceHolder), ex: Você pode desenha o cabeçalho e o menu da sua página em uma Master Page, e eles se repetirão nas páginas associadas a ele.

Adicione um novo item, clicando com o botão direito no seu projeto:

image

Escolha o template Master Page:

image

A Master Page tem funcionalidades similares a de uma página APS.NET comum. Seu layout ficará assim:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Principal.master.cs" Inherits="TutorialSkin.MasterPage.Principal" %>

<!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>
    <link href="../Estilos/Geral.css" rel="stylesheet" type="text/css" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div id="divCabecalho" class="Cabecalho">
        <p>Demonstração de Themas/Skins.</p>
    </div>
    <div class="Menu">
        <asp:DropDownList ID="DdlTemas" runat="server" AutoPostBack="true" >
            <asp:ListItem>Azul</asp:ListItem>
            <asp:ListItem>Verde</asp:ListItem>
            <asp:ListItem>Laranja</asp:ListItem>
        </asp:DropDownList>   
    </div>
    <div>
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>

(ASP e HTML da Master Page)

image

Basicamente adicionei uma “div” de cabeçalho e outra “div “de menu. No menu adicionei um “DropDownList” com a lista dos temas, definidos na mão mesmo, com “ListItem”. É importante observar que este “DropDownList” tem a propriedade “AutoPostBack” setada para “true”, mesmo não disparando nenhum evento.

Atente-se à propriedade “class” das “divs”, pois ela estará ligada aos arquivos de estilos que criaremos.

Dica: Cuidado, pois a Master Page repetira o código HTML gerado pelo ASP.NET em cada página relacionada a ela. Para amenizar isto, use de boas técnicas de design, como o CSS, por exemplo.

Adicionando Skin:

Adicione novos itens do tipo Skin, nomeando eles de acordo com a base da skin, no meu caso coloque os seguintes: Azul, Verde, Laranja.

image

image

Ao adicionar as skins o Visual Studio perguntará se deseja usar a pasta padrão para o controle de temas, por comodidade organizacional responderemos que sim.

Cada arquivo skin conterá as definições de aparência dos componentes, e cada pasta de tema pode conter os arquivos de CSS necessários. Logo nossa estrutura de pastas e arquivos ficaram organizadas assim:

image

Note que incluí uma pasta “Estilos” onde ficaram os arquivos de CSS mais gerais. E para cada tema incluí o CSS relativo ao tema. Incluí também uma pasta com algumas imagens de cabeçalho para o exemplo.

CSS:

CSS: são nossos arquivos de estilo, definição de cores, design e layout das páginas.
O arquivo nomeado de “Geral.css” ficou com definições de layout:

body
{
margin: 0px;
padding: 0px; 
}

.Menu
{
width: 698px;
text-align: right;
}

(CSS do arquivo “Geral.css”)

Obs: A master page deve conter a referência deste arquivo.

<head runat="server">
    <title>Untitled Page</title>
    <link href="../Estilos/Geral.css" rel="stylesheet" type="text/css" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>

(Definição do “Geral.css” na master page)

Para os arquivos de CSS dentro dos temas apenas defini a imagem cabeçalho correspondente:

.Cabecalho
{
background-image: url("/Imagens/CabecalhoAzul.jpg");
font-family: Verdana;
font-size: 30px;
font-weight: bold;
text-indent: 70px;
width: 700px;
height: 70px;
color: #229ABD;
line-height: 70px;
}

(Definição do cabeçalho via CSS)

Definição da skin:

O arquivo de skin, como já mencionado, define a aparência dos componentes da sua página, ex:

<asp:DropDownList runat="server" ForeColor="Blue"></asp:DropDownList>

<asp:Label runat="server" ForeColor="Blue"></asp:Label>

<asp:TextBox runat="server" ForeColor="Blue" BorderWidth="1px" BorderStyle="Solid" BorderColor="Blue"></asp:TextBox>

<asp:Button runat="server" BorderStyle="Solid" BorderColor="Blue" BorderWidth="1px" ForeColor="Blue" BackColor="#EEEEEE"></asp:Button>

(Definição dos componentes via skin)

Note que é como definirmos um objeto na tela, porém setando apenas as propriedades visuais. Neste arquivo defini o visual dos objetos “DropDownList”, “Label”, “TextBox” e “Button”, más não se limita somente nisto, podemos definir detalhadamente o visual de um “GridView” por exemplo.

As páginas do Site/Aplicação:

Antes de adicionar uma página, adicionaremos um arquivo que servirá de base para nossas páginas: uma classe que herdará a classe “System.Web.UI.Page”, é nele que será realizada a troca das skins de forma simples e transparente.

image

Realizaremos a troca da skin sobrescrevendo o método “Page_PreInit()”, este método é executado antes da página ser renderizada.

using System;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace TutorialSkin
{
    public class PaginaBase : Page
    {
        // -> Realiza a troca de skin antes de renderizar a página.
        protected void Page_PreInit(object sender, EventArgs e)
        {
            string tema = Request[Master.FindControl("form1").FindControl("DdlTemas").UniqueID];

            if (!string.IsNullOrEmpty(tema))
                Theme = Request[Master.FindControl("form1").FindControl("DdlTemas").UniqueID];
        }
    }
}

(Codificação da página base)

Para definirmos o tema atual de nossas páginas tivemos de verificar o “Request” do “DropDownList” , que colocamos na master page e causou um post back devido ao “AutoPostBack”. Resgatamos seu valor pelo seu “UniqueID”, então cuidado na hora de dar os finds, principalmente com o form da master page.

Agora nos resta trabalharmos nas páginas (arquivos “*.aspx”), atentando-nos “ àlguns detalhes.

Primeiramente as páginas devem ser associadas à nossa master page, assim sendo, adicionaremos um item do tipo “Web Content Form”.

image

image

Agora com nossa página adicionada, temos o seguinte code behinde:

    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }

(Página ASP recém adicionada)

Devemos simplesmente alterar a herança do code behind para nossa página base, ficando assim:

    public partial class Default : PaginaBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }

(Herança alterada)

Para o exemplo eu apenas coloquei três componentes na página para verificarmos o funcionamento dos temas, são eles: “Label”, “TextBox”, “Button”.

<%@ Page Language="C#" MasterPageFile="~/MasterPage/Principal.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TutorialSkin.Default" Title="Themes & Skin by Eduardo Spaki" Theme="Azul" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <div>
        <p><asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></p>
        <p><asp:TextBox ID="TextBox1" runat="server">Exemplo</asp:TextBox></p>
        <p><asp:Button ID="Button1" runat="server" Text="Button" /></p>
    </div>
</asp:Content>

(“.aspx”” da página recém adicionada)

image

Na tag “Page” eu coloquei a propriedade “Theme” como “Azul” para deixar este tema como o padrão da página.

Não tem mais segredo, somente testar e ver o resultado, podendo programar o restante do site de acordo com as necessidades. E toda vez que for selecionado um tema no “DropDownList” que está definido na master page, a aplicação trocará de aparência, de acordo com as skins e CSSs dos temas.

Testando:

Compile e veja os resultados, trocando o tema no “DropDownList”:

image 

image

image

Considerações Finais:

A definição de um tema default pode ser pelo arquivo de configuração da aplicação “web.config”:

<configuration>
    <system.web>
        <pages theme=“Azul” />
    </system.web>
</configuration>

(Definição do tema default  no web.config)

... ou por página, na tag “Page”, propriedade “Theme”:

<%@ Page Language="C#" MasterPageFile="~/MasterPage/Principal.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TutorialSkin.Default" Title="Themes & Skin by Eduardo Spaki" Theme="Azul" %>

(Definição do tema default por página)

Algumas outras idéias podem ser utilizadas para fazer com que os temas sejam personalizados por funcionalidades e/ou usuários, como: cookies, membership etc.

Os componentes também podem conter uma referência pela propriedade “SkinID”.

Algo um pouco chato talvez seja algumas repetições de CSS e linhas nas skins.

Conclusão:

Sintetizado, estas funcionalidades e dicas agregam um valor ao resultado final de seu projeto que, em muitos outros casos, desenvolvedores gastaram tempo e dinheiro para fazer algo que funciona-se de forma duvidosa.

Combinamos tecnologias e boas práticas para desenvolver algo correto, leve e funcional.

Não se deve ficar engessado, devemos usufruir desta tecnologia que nos poupa codificação e repetição de inúmeras linhas de códigos e tags. O ASP e o .NET estão aí para facilitar e flexibilizar!

Qualquer sugestão ou dúvida: comentem ou entrem em contato, seu feedback é importante!

Caso queiram, posteriormente posso estar falando sobre Master Page e Master Page aninhada... talvez sobre aplicação multi-idiomas, depende do que opinarem...

Espero ter sido útil e aberto algumas mentes. Abraços...

Referências:
http://www.codeproject.com/KB/aspnet/ThemesAndSkins.aspx
http://aspalliance.com/959
http://www.linhadecodigo.com.br/Artigo.aspx?id=958

Download do Exemplo!

Abraços... Eduardo Spaki.

1 comentários:

MatZ disse...

Boas, o exemplo está excelente!
Só que agora tenho um problema, ao criar mais páginas associadas à masterpage, mudando o tema numa delas, quando mudar de página o tema não se mantém. Pode ajudar-me numa solução?
abraços