domingo, 7 de noviembre de 2010

Temas en ASP.NET

En el siguiente post vamos a ver sobre los temas en ASP.NET, esto es Theme y StylesheetTheme.

Estos atributos se pueden establecer desde:

·         Directiva @ Page.

·         Elementos pages del web.config.

Cabe mencionar que un tema (en cualquiera de sus versiones) “no” se puede aplicar a una página maestra, sólo a páginas de contenido.

Su ubicación es una carpeta especial de ASP.NET, que tiene que estar en la raíz de nuestra aplicación o sitio web y su nombre es App_Themes\<Tema>.

La propiedad System.Web.UI.Control.EnableTheming  permite decidir si un control se ve o no afectado por el tema. Al respecto, es importante saber que EnableTheming no funciona con StylesheetTheme (pero sí funciona con Theme). Ver más información en http://connect.microsoft.com/VisualStudio/feedback/details/104930/enabletheming-does-not-apply-when-stylesheettheme-is-applied

StylesheetTheme se aplica a la vista de diseño, por el contrario Theme no se aplica.

Sólo puede haber un tema predeterminado por control, esto es que en un fichero .skin o en varios ficheros .skin, no puede haber 2 declaraciones predeterminadas de tema (sin SkinID) para un mismo control.

Por defecto, todas las propiedades de un control son “skinables” (término más o menos acertado que me acabo de inventar) a no ser que es especifique el atributo Themeable(False) en la propiedad. Por ejemplo, la propiedad ID (que no skinable) tiene la siguiente declaración en System.Web.UI.Control:

<Themeable(False)> _

Public Overridable Property ID As String

En un tema puede haber cualquier número de ficheros .skin.

Una propiedad importante en SkinID que permite tener varias definiciones de tema para un mismo control.  De este modo, es posible tener una definición de tema predeterminada para un control (tampoco es necesario y podría no existir) y tantas definiciones extras de tema como queramos a través de la propiedad SkinID.

De este modo y para un botón por ejemplo podríamos tener la siguiente definición de temas en un fichero .skin (o en varios según la elección del programador):

<asp:Button runat="server" BackColor="Aqua" ForeColor="Red" />

<asp:Button runat="server" Font-Bold="True" SkinID="Negrita" />

 

Y tener una página .aspx con el siguiente código:

<asp:Button ID="Button1" runat="server" Text="Button 1" />

<asp:Button ID="Button2" runat="server" Text="Button 2" SkinID="Negrita" />

 

Una diferencia importante entre Theme y StylesheetTheme es como se “combinan” las propiedad definidas en la declaración del desde el marcado (.aspx, .ascx, etc.) y las propiedades definidas por un tema en un fichero .skin.

·         Theme

o   Primero las propiedades del control.

o   Después las propiedades del tema y se es preciso, se sobreescriben las propiedades comunes.

·         StylesheetTheme

o   Primero las propiedades del tema.

o   Después las propiedades del control y se es preciso, se sobreescriben las propiedades comunes.

De este modo, Theme es más importante (jerárquicamente hablando) que StylesheetTheme.

Y si pasa que establecemos a la vez ambas propiedades (sí, ya sé que es raro, pero poder se puede…) pues entonces tenemos la siguiente precedencia de propiedades http://quickstart.developerfusion.co.uk/QuickStart/aspnet/doc/themes/stylesheettheme.aspx#precedence

·         Primero propiedades de StyleSheetTheme.

·         Después propiedades control (que sobreescriben las propiedades de StyleSheetTheme).

·         Por último propiedades de Theme (que sobreescriben las propiedades de StyleSheetTheme).

 

Aunque lo siguiente no es una característica concreta de los temas, es importante conocerla puesto que a veces nos ayuda a construir un código HTML más preciso. La característica de la que hablamos es que ASP.NET no procesa propiedades que desconoce, y por el contrario simplemente las sirve sin ningún tratamiento. Así por ejemplo, la siguiente definición de un botón:

 

<asp:Button ID="Button2" runat="server" Text="Button 1" MiAtributo="MiValor" />

 

Tendrá como resultado en el navegador cliente:

 

<input type="submit" name="Button2" value="Button 1" id="Button2" MiAtributo="MiValor" />

 

Fijarse que MiAtributo es un atributo de nuestra invención pero que no produce ningún error en ASP.NET y además se descarga en el navegador cliente. Pues bien, esto es válido tanto en el marcado de una página .aspx como en un fichero .skin.

 

Por último, simplemente decir que desde el servidor se podría acceder a MiAtributo a través del siguiente código:

 

Button2.Attributes.Item("MiAtributo")

 

 

Para establecer el tema de una página de forma programática hay que tener en cuenta las siguientes consideraciones:

·         Si queremos establecer la propiedad Theme.

o   Tiene que ser desde el evento Page_PreInit.

·         Si queremos establecer la propiedad StylesheetTheme.

o   Tenemos que sobreescribir la propiedad StyleSheetTheme.

·         Si queremos establecer la propiedad SkinID de un control
(sólo para Theme ya que no funciona con StyleSheetTheme).

o   Tiene que ser desde el evento Page_PreInit.

·         Para controles añadidos de forma dinámica y si optamos por StyleSheetTheme

o   Es necesario llamar al método ApplyStyleSheetSkin.

 

Una situación especial que merece ser explicada es como se comportaría el siguiente código:

 

<asp:Button ID="Button1" runat="server" Text="Button 1"
BackColor="Aqua" Style="background-color: Red;"
/>

 

Que resultará en el siguiente código HTML

 

<input type="submit" name="Button1" value="Button 1" id="Button1"
style=" background-color: Aqua;background-color: Red;"
/>

 

Como se puede observar las propiedades de System.Web.UI.Control que se traducen en propiedades CSS en línea, se anexan por delante de cualquier valor que ya tuviera el atributo style, de este modo, aunque el color de fondo se establezca al color Aqua, después se establece al color Red y por ser último, vence Red.

 

 

Hasta ahora hemos centrado el trabajo con los temas en los ficheros .skin pero otro importante ámbito a estudiar sobre los temas y su comportamiento son los ficheros de hojas de estilo (.css).

Para no hablar más sobre ello y dejar este asunto zanjado, la rutas de las imágenes tanto en un fichero .skin como en un fichero .css que esté dentro de un tema, son “relativas al tema” esto que si creamos una carpeta Images dentro de nuestra carpeta de tema, podríamos tener el siguiente código y ASP.NET resolvería en tiempo de ejecución la ruta definitiva a las imágenes según la página cargada.

Fichero .skin

<asp:ImageButton runat="server" ImageUrl="Images/save.png" />

 

Fichero .css

.button

{

    background-image: url(Images/save.png);

}

Volviendo a cómo trabaja un tema con hojas de estilos .css, hay que tener en cuenta lo siguiente:

·         ASP.NET inyecta automáticamente etiquetas link con referencias a las hojas de estilo encontradas en el directorio del tema.

·         Inyecta estas referencias para todas las páginas .aspx de la aplicación.

·         Las inyecta en orden alfabético, esto es que inyectará primero 1.css que 2.css, y además primero inyecta los ficheros .css del directorio raíz del tema y después los siguientes ficheros que vaya encontrado por subcarpeta (si los hubiera).

·         En caso de que la página tuviera ya algún enlace a una hoja de estilo, ASP.NET inyecta las nuevas referencias:

o   Antes de las existentes (si StyleSheetTheme), justo después de <html>.

o   Después de las existentes (si Theme), justo antes de cerrar </head>.

Por último, mencionar que es posible definir temas a nivel de servidor (ya sea IIS o Cassini), para más información ver http://weblogs.asp.net/vimodi/articles/ThemesFaqs.aspx

Un saludo!

No hay comentarios:

Publicar un comentario