Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO INTERFAZ DE USUARIO Plantilla de trabajo Uno de los problemas que nos encontramos a la hora de comenzar una aplicación es el formato con el que vamos a realizar una aplicación, si es de Campus Virtual, si es una aplicación aislada o recientemente si debe estar integrada en Vualà. Esto lo soluciona de una forma muy sencilla las plantillas creadas y la clase UAPage (que veremos posteriormente), que sin modificar una línea de código, podemos visualizar la aplicación con los diferentes entornos. Aplicación integrada en el marco de Campus Virtual Aplicación independiente Aplicación integrada en una página de Vualà 1 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Control versiones idiomática Desde el entorno de Visual Studio, tenemos controlados con los ficheros de recursos todo el tema de la traducción de los contenidos de nuestra aplicación. En las plantillas y en la clase UAPage hemos homogeneizado la detección y gestión de las versiones idiomáticas, permitiendo pasar de una versión a otra con un solo clic (en las aplicaciones independientes en la barra inferior, y en Vualà en la barra superior). El programador sólo debe controlar las versiones idiomáticas en la página de acceso, en el resto de páginas la propia plantilla se encarga de su gestión. Aplicación independiente en castellano Aplicación independiente en valenciano Aplicación integrada en Vualà en castellano Aplicación integrada en Vualà en valenciano 2 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Estilos personalizados Es muy importante que el usuario identifique la información de un primer vistazo y sobre todo que pueda corregir los errores. Si nos fijamos en la siguiente ventana identificamos algunos de los elementos. Resaltado de los campos que dan problema Ayuda en cada campo 3 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Personalización de los avisos (dependiendo de la gravedad) Sumario de los errores Personalización de los botones Personalización de los fieldset 4 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Trabajo con layouts o columnas Consigue que el resultado final sea igual independiente de la resolución con la que estemos trabajando. En un futuro muy cercano se ajustará para que se pueda ver igualmente en los móviles. Igualmente unifica que el resultado sea el mismo independiente del navegador. 1024x768 1280x1024 1920x1024 5 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Uso Los requisitos mínimos para trabajar con las plantillas son las siguientes: • Plantilla o plantillas con las que queremos trabajar. Disponemos actualmente de 3 aunque una de ellas realmente la forman 3 (la de Vualà necesita una por cada idioma) En http://desarrollocpd.campus.ua.es/Plantillas/material/masterpages.zip podemos encontrarlas o MasterPage.master o MasterPageCV.master o MasterPageUA.es.master - MasterPageUA.ca.master y MasterPageUA.en.master En el caso de MasterPage.master debemos copiar también la carpeta/guiaestilo/masterpages /App_LocalResources para que los textos aparezcan en el idioma seleccionado. Para seleccionar la plantilla al crear la página, marcamos seleccionar la página principal Y dentro de la carpeta masterpages, seleccionamos la que nos interese. 6 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO • Clase para la gestión automática de los idioma/guiaestilo/App_Code/UAPage.cs Todas nuestras páginas deben heredar de ésta. El proceso es muy sencillo, cuando creamos una página, por defecto, nos genera un código como el siguiente: Reemplazamos System.Web.UI.Page por ua.UAPage. Desde ese momento en la carga de la página determina el idioma y configura la página a dicho idioma. 7 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Importante: la variable que almacena el idioma del usuario es Session["idioma"]. Todos usaremos la misma para unificar criterios. En el momento que se defina, será ese el idioma por defecto hasta que lo cambie el usuario. Los valores posibles son es, ca y en. Se ha tomado ca y no va, para unificar con el estándar internacional. La primera vez que accede, si no hemos definido ningún idioma por defecto, tomará por defecto el idioma que tenga configurado el navegador y en que caso de que no sea detectable, cogerá castellano. • Por último hay que definir una variable en web.config para indicar de dónde se obtienen los CSS, las llamadas Javascript básicas para el funcionamiento de las plantillas. Buscamos appSettings Y le añadimos nuestra variable En desarrollo <add key="servidorscripts_masterpage" value="http://dessarrollocpd.campus.ua.es/guiaestilo"/> En producción <add key="servidorscripts_masterpage" value="http://cvnet.campus.ua.es/guiaestilo"/> 8 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Maquetando Como se ha comentado anteriormente todo debe estar integrado en columnas (layout). Esto nos facilita que el contenido se ajuste a cualquier pantalla, aunque es posible que hasta que nos amoldemos a crear paneles para cada línea, se nos haga algo tedioso. Trabajando con un formulario básicos de una sola columna. Si nos fijamos en el siguiente formulario Se necesitan 4 paneles con el estilo columnas_1, uno por cada fila que vamos a gestionar. Y dentro el label y el textbox / DropDownList / etc. Correspondiente 9 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Trabajando con dos columnas Lo primero es crear dos paneles, para posteriormente asignarles el estilo indicando el tipo de columna. Si queremos que sean dos columnas de igual tamaño, seleccionaremos el estilo, columnas_2. <asp:Panel ID="Panel1" runat="server" CssClass="columnas_2"> Columna de la izquierda </asp:Panel> <asp:Panel ID="Panel2" runat="server" CssClass="columnas_2"> Columna de la derecha </asp:Panel> El resultado es el siguiente. Si queremos trabajar con una columna de menos tamaño (1/3) y otra de mayor tamaño (2/3), seleccionaremos dos estilos. <asp:Panel ID="Panel3" runat="server" CssClass="columnas_1_3"> Columna de la izquierda </asp:Panel> <asp:Panel ID="Panel4" runat="server" CssClass="columnas_2_3"> Columna de la derecha </asp:Panel> El resultado es el siguiente. 10 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Se puede cambiar el orden, para que la primera sea más grande (columnas_2_3) y la otra más pequeña (columnas_1_3). No mezclar columnas_2 con columnas_1_3 o columnas_2_3. 11 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Trabajando con Fieldsets o agrupación de campos En el cumplimiento de la Ley de Accesibilidad, debemos agrupar los campos del mismo estilo o de la misma temática (por ejemplo datos personales) dentro de un fieldset. La utilidad es clara, una persona que no quiera rellenar los datos personales (porque por ejemplo ya los tenga rellenados), puede saltarse la sección completa, sin tener que ir campo por campo esperando a llegar al que le interese. Para insertar un fieldset en .NET, el proceso es muy sencillo, añadimos un panel, en ese momento le podemos aplicar el layout o columnado (lo deben tener todas las filas), y por último para indicar que es un fieldset, debemos acudir a la propiedad GroupingText y ponerle la descripción (o legend) del fieldset). Si queremos un fieldset que ocupe una única columna. <asp:Panel ID="Panel1" runat="server" CssClass="" GroupingText="Datos Personales"> Contenido </asp:Panel> Resultado. Hay 3 diseños para los fieldsets: 1. El que viene por defecto y que muestra un simple línea horizontal 12 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO 2. Aplicando CssClass=”redondeado” obtendremos un borde redondeado alrededor de todos los elementos. 3. Aplicando CssClass=”simple”, hace un borde simple cuadrado alrededor de todos los elementos. Trabajando con Label asociados a campos del formulario Al igual que se ha comentado anteriormente, y cumplimiento de la Ley de Accesibilidad, debe gestionarse todos los campos del formulario para que haya un Label asociado a cada campo. Para ello usaremos la propiedad AssociatedControlID que nos proporciona el componente Label. Si queremos generar un campo que solicita el nombre y otro los apellidos <asp:Panel ID="Panel2" CssClass="columnas_1" runat="server"> <asp:Label ID="LabelNombre" runat="server" AssociatedControlID="TextBoxNombre" Text="Label">Nombre</asp:Label> <asp:TextBox ID="TextBoxNombre" runat="server"></asp:TextBox> </asp:Panel> <asp:Panel ID="Panel3" CssClass="columnas_1" runat="server"> <asp:Label ID="LabelApelliods" AssociatedControlID="TextBoxApellidos" runat="server" Text="Label">Apellidos</asp:Label> <asp:TextBox ID="TextBoxApellidos" runat="server"></asp:TextBox> </asp:Panel> 13 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Como se comentó anteriormente, es necesario agrupar todos los elementos en Panels (indicando el número de columnas). Esa es la razón de que cada label / TextBox esté dentro de un panel. De esa manera nos aseguramos que se ve bien en cualquier dispositivo y resolución. En caso de no hacerlo es posible que en determinadas resoluciones, un label se ponga detrás de un TextBox o que el TextBox baje abajo, etc. Ya hay unos tamaños predefinidos para los Label que permiten unificar el aspecto con el que se verán en diferentes dispositivos (pequeno, medio-s, medio, medio-x y grande). Hay que indicarlo en CssClass del Label <asp:Panel ID="Panel5" CssClass="columnas_1" runat="server"> <asp:Label ID="Label1" runat="server" CssClass="pequeno" AssociatedControlID="TextBox1" Text="Label">pequeno</asp:Label> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </asp:Panel> Trabajando con campos del formulario Se han definido tamaño para los campos TextBox. En este caso disponemos de 4 tamaños (pequeno, medio, medio-x y grande). <asp:Panel ID="Panel13" CssClass="columnas_1" runat="server"> <asp:Label ID="Label8" runat="server" CssClass="medio" AssociatedControlID="TextBox8" Text="Label">medio</asp:Label> <asp:TextBox ID="TextBox8" CssClass="medio" runat="server"></asp:TextBox> </asp:Panel> 14 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Si deseamos incorporar una ayuda al campo que se active al pulsar en éste usaremos la propiedad ToolTip de cualquiera de los elementos de un formulario. <asp:Panel ID="Panel15" CssClass="columnas_1" runat="server"> <asp:Label ID="Label10" runat="server" CssClass="medio" AssociatedControlID="TextBox10" Text="Label">grande</asp:Label> <asp:TextBox CssClass="grande" ID="TextBox10" ToolTip="Ejemplo de un mensaje de ayuda asociado al campo" runat="server"></asp:TextBox> </asp:Panel> Caso particular de los radiobuttons y checkbox Visual Studio de dos elementos muy útiles para trabajar con radio y checks que son RadioButtonList y CheckBoxList. El problema es que este elemento, por defecto se comporta como una tabla. Esto se configura con la propiedad RepeatLayout, que por defecto tiene el valor de Table. Siempre debe tener el valor a Flow. No es un elemento tabular, y por tanto no debemos usarlo si no es para ese propósito. Además nos da dos posibilidades, o mostrarlo en horizontal o en vertical. En el ejemplo siguiente vemos los checks y los radio en ambos formatos. Como el código que genera, siendo accesible, no es muy ortodoxo, hay que indicar al RadioButtonList o al CheckBoxList el tipo que es. Eso lo indicamos en el CssClass con radio o checkbox. 15 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO <asp:CheckBoxList ID="CheckBoxList2" runat="server" CssClass="checkbox mediano" RepeatDirection="Vertical" RepeatLayout="Flow"> <asp:ListItem>Moda</asp:ListItem> <asp:ListItem>Televisión</asp:ListItem> </asp:CheckBoxList> También es posible gestionar el tamaño de los labels en cada uno de los casos. En el horizontal es importante para no separar mucho una opción de otra. Para ello usaremos los tamaños de los labels como antes (pequeno, medio-s, medio, medio-x y grande). <asp:CheckBoxList ID="CheckBoxList2" runat="server" CssClass="checkbox pequeno" RepeatDirection="Horizontal" RepeatLayout="Flow"> <asp:ListItem>Moda</asp:ListItem> <asp:ListItem>Televisión</asp:ListItem> </asp:CheckBoxList> Campos obligatorios Para resaltar aquellos campos que son obligatorios usaremos un sencillo * en color rojo. Para llevarlo a cabo se debe marcar el campo TextBox, DropDownList, etc, con la clase required. Además tiene que estar el Label asociado al campo con la propiedad AssociatedControlID apuntando al campo, en caso contrario, no incluirá la marca al Label. <asp:Panel ID="Panel22" CssClass="columnas_1" runat="server"> <asp:Label ID="Label15" runat="server" CssClass="medio" AssociatedControlID="TextBox7" Text="Label">pequeno</asp:Label> <asp:TextBox ID="TextBox7" CssClass="pequeno required" runat="server"></asp:TextBox> </asp:Panel> Validación de campos y agrupación de mensajes en Summary La validación de los campos también se va a hacer de una forma homogénea. Para ello se crean los validadores y se marca la propiedad Display a none. Es recomendable que no aparezca el mensaje al lado del campo, porque como ya hemos comentado anteriormente, se puede descuadrar dependiendo del dispositivo con el que accedamos. Por eso usaremos ValidationSummary para recoger todos los mensajes de error. 16 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Se dispone de varios estilos para aplicar a los sumarios (msg-error, msg-ok, msg-warn y msg-info) cada uno con un color. El más común es msg-error que muestra el aviso en rojo. Además se puede personalizar el título del sumario con la propiedad HeaderText. Si queremos que tenga el formato que se ve en la imagen, negrita, letra más grande y un pequeño borde en la parte inferior, debemos incluirlo dentro de la etiqueta <h3> El resultado con los otros formatos sería el siguiente msg-warn msg-ok msg-info 17 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO Importante Como el resto de los elementos, el sumario debe estar dentro de un panel y además con un estilo columnas_x (en este ejemplo columnas_1). En caso de no ponerlo, es posible que el estilo se aplique al Panel anterior, el que tiene todos los campos. <asp:Panel ID="Panel4" CssClass="columnas_1" runat="server"> <asp:ValidationSummary ID="ValidationSummary1" CssClass="msg msg-error" runat="server" HeaderText="&lt;h3&gt;Datos incorrectos&lt;/h3&gt;" /> </asp:Panel> Resaltado de los campos que contienen errores Por defecto, el sistema resalta de forma automática, todos aquellos campos que provocan el error. Además se sitúa sobre el primer campo que contenga un error. Si tiene definida la ayuda o ToolTip, se activará. En campo de tipo RadioButtonList o CheckBoxList el proceso es el mismo, incluir en CssClass required. <asp:RadioButtonList ID="RadioButtonList1" runat="server" CssClass="radio pequeno required" RepeatDirection="Horizontal" RepeatLayout="Flow"> <asp:ListItem>Hombre</asp:ListItem> <asp:ListItem>Mujer</asp:ListItem> </asp:RadioButtonList> El resultado es el siguiente 18 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO 19 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO INTEGRACIÓN CON VUALÀ Consideraciones previas Cada vez se hacen más peticiones de que las aplicaciones que desarrollamos estén integradas dentro de las páginas de Vualà. El usuario que navega no debe notar que ha cambiado de un entorno a otro, como ocurre actualmente, aunque la dirección cambie de un servidor a otro. Se ofrecen dos posibilidades, que todo vuestro entorno esté en Vualà, o que puedas personalizar una página concreta, o incluso bajo unas determinadas condiciones tenga un entono u otro (mirar anexos) Accesibilidad Las plantillas de Vualà, cumplen la normativa de accesibilidad que deberíamos cumplir en todas nuestras aplicaciones. Con un poco de cuidado y con algunos consejos que os daremos más tarde, podéis hacer vuestra aplicación sea accesible y esté preparado para diferentes entornos (diferentes resoluciones, tablets, móviles, etc.) Espacio para acceder a las plantillas Por medidas de seguridad las aplicaciones .NET no pueden acceder a las plantillas que hay en otras aplicaciones, para solucionar esta limitación hay que solicitar al área Windows, por medio de los partes: https://aplicacionesua.cpd.ua.es/proyectos/formulario/generaParte.asp?id=22&idioma=C, que nos cree una carpeta virtual /nombrenuestraaplicacion/plantillas a las plantillas de desarrollo. Es conveniente pedirlo para nuestra máquina de desarrollo como para preproducción (si ya está creado el espacio en preproducción). Instalación Web.Config Si deseamos que TODAS nuestras páginas tengan el estilo de una página de Vualà, sólo hay que añadir dos entradas en appSetting. La primera es la página de Vualà que se usara como plantilla (pagina-vuala) y otra que indicamos si queremos que sea aplique a todas las páginas (todo-vuala). La página que seleccionemos es independiente del idioma por lo que podemos coger cualquiera de las 3 versiones de la página que queremos que sea la plantilla y ya el sistema se encargará de obtener sus equivalencias. <appSettings> <add key="pagina-vuala" value="http://ssyf.ua.es/es/accesopdi/acceso-pdi.html"/> 20 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO <add key="todo-vuala" value="S" /> </appSettings> ¡IMPORTANTE! No se puede coger una página raíz de un sitio, como por ejemplo http:/si.ua.es/. Al menos se tiene que seleccionar la carpeta del idioma http:/si.ua.es/es/ o lo más sencillo, navegar a la página pulsar otro idioma, volver a pulsar el idioma inicial, y copiar toda la dirección (en el caso del SI, verás que realmente la página principal se llama http://si.ua.es/es/servicio-de-informatica.html) Nueva Plantilla de Trabajo (Masterpageua.master) Se ha creado una página maestra muy sencilla, que muestra un esqueleto, sin nada, de la estructura de Vualà (una zona superior para la cabecera, un espacio para los menús y la zona real de trabajo). El resto de elementos (cabecera, menús, pie, etc.) se mostrarán en el momento que ejecutemos la aplicación. La plantilla la podemos descargar de: http://desarrollocpd.campus.ua.es/Plantillas/material/masterpages.zip Ficheros de Trabajo Hay dos ficheros que ayudan en el proceso de gestión de las plantillas. Para poder hacer uso de ellos, los descargamos y los copiamos en AppCode http://desarrollocpd.campus.ua.es/Plantillas/material/App_Code.zip UAPage.cs Este fichero se encarga de detectar el idioma con el que estamos trabajando y de poner la plantilla que corresponda. Para poder hacer uso de esta clase debemos acceder a cada fichero .cs, asociado a nuestras páginas, y cambiar : System.Web.UI.Page por 21 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO : ua.UAPage ServicioPlantillas.cs Es una clase que encapsula las llamadas al WebService que nos gestiona las plantillas. Se usa desde UAPage.cs y sólo en caso de que necesitemos gestionar nosotros las plantillas, haremos uso de esta clase. NOTA: Si queremos que no nos olvidemos de poner ua.UAPage, se puede añadir una etiqueta en web.config para que nos obligue a hacerlo. En caso contrario nos dará un error de compilación. Dentro de <system.web> <system.web> … <pages pageBaseType="ua.UAPage"> <namespaces> <add namespace="ua" /> </namespaces> </pages> … Anexos Gestionar el uso de plantillas En caso que nos interese decir cuándo y cuál será la plantilla a mostrar, tenemos que tener en cuenta lo siguiente: • Debemos modificar la plantilla o MasterPage en el evento OnPreInit de UAPage. En cualquier otro caso puede provocar que los datos de nuestro formulario se pierdan (incluso el PreInit de 22 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO nuestra página). Os recomiendo repasar el documento Ciclo de Vida de una página ASP.NET (http://msdn.microsoft.com/es-es/library/ms178472.aspx) • Se han normalizado ciertos elementos: • Enlaces a idiomas para la plantilla de Vualà y en las plantillas de Aplicaciones. Los Ids son LinkButtonValencia, LinkButtonEnglish y LinkButtonCastellano • Variables session para la gestión de los idiomas y las plantillas. Session["Plantilla"] para almacenar la ubicación física de la página master y Session["idioma"] para indicar el idioma actual de la aplicación (es, en y ca) Ejemplo para cambiar la plantilla desde un desplegable Un ejemplo muy sencillo para poder probar la potencia es hacer un formulario con un desplegable (DropDownListPlantilla), que nos permita seleccionar una plantilla determinada. El desplegable para el ejemplo puede tomar 3 valores CV, AppUA o VUALA. En los dos primeros casos coge una plantilla local nuestra, mientras que en el 3º caso obtiene por medio de un WebService, la plantilla de Vualà que le corresponde. Lo siguiente es modificar en UAPage.cs el evento OnPreInit para detectar la plantilla antes de que se comience a gestionar los componente, los viewstates, etc. Recordar lo comentado al principio en caso de que gestionemos la modificación de la plantilla en cualquier otro evento podemos obtener dos resultados, o que se pierdan los valores de los campos que ya estuvieran rellenos o que se refresque la plantilla en el siguiente evento, y no en el actual, porque las plantillas sólo se refrescan en un PreInit. 23 Programación avanzada en .NET con C# Servicio de Informática INTERFAZ DE USUARIO if (Page.IsPostBack) { string controlID = Request.Params["__EVENTTARGET"]; switch (controlID) { case "ctl00$MainContent$DropDownListPlantilla": if (Request.Form["ctl00$MainContent$DropDownListPlantilla"] != null) { switch (Request.Form["ctl00$MainContent$DropDownListPlantilla"]) { case "CV": Session["Plantilla"] = "~/masterpages/MasterPageCV.master"; break; case "AppUA": Session["Plantilla"] = "~/masterpages/MasterPage.master"; break; case "VUALA": if (ConfigurationManager.AppSettings["pagina-vuala"] != null) { // Recuperamos la plantilla por medio del WebService var wsPlantillas = new WebServicePlantillas(); // Si la plantilla la recuperemos de las variables AppSetting var plantillaUrl = ConfigurationManager.AppSettings["pagina-vuala"] .ToString(); // Si la indicamos a mano // var plantillaURL = "http://si.ua.es/es/" Session["Plantilla"] = wsPlantillas.ObtenerMasterPage(plantillaUrl, Session["idioma"].ToString()); } break; default: Session["Plantilla"] = null; break; } } break; } } // Asignamos la plantilla if (Session["Plantilla"] != null) { MasterPageFile = Session["Plantilla"].ToString(); } 24