16 septiembre 2008

Falta grave de recursos en librerias

Ya tengo muy delimitado el funcionamiento de los temas y estilos, basado en los diccionarios de recursos de WPF. En líneas generales, tenemos una librería Temas que ofrece un tema genérico aplicable a cualquier aplicación, el cual básicamente no modifica el estilo básico del sistema pero añade nuevos estilos y plantillas genéricas, como EstiloVentana (para poder modificar todas las ventanas, ya que establecer la key a Window no funciona), EstiloTitulo (para los label que se usan como título), EstiloEtiquetaDato (para los label que se usan como dato y no como etiqueta)... Y muchos otros estilos comunes.
A continuación, cada librería que incluye interfaz complementa este diccionario con nuevos estilos que necesita, a la vez que hace uso de los recursos "heredados" de Temas. Así la librería publica a su vez un diccionario, normalmente de nombre Generico.xaml.
Por último, en la aplicación se reunen estos diccionarios en uno propio Generico.xaml, y se establece en App.xaml como diccionario de recursos de la aplicación, de forma que se utilizará en diseño en VS2008 automáticamente.
Y aquí reside el problema: en que esto que podemos hacer en la aplicación no podemos hacerlo en las librerías, es decir, no puede definirse el diccionario de recursos global de la librería para ser utilizado en diseño, por lo que si incluimos algo tan simple como {StaticResource EstiloVentana} como estilo de una ventana, esta ya no se muestra en el diseñador, alegando que ese recurso no se encuentra.
Según leo aquí, Marco Zhou dice que esa función debe realizarla Themes\generic.xaml en las librerías, un archivo que debe residir en una carpeta Themes, y que la librería debe contener un atributo ThemeInfo para informar de que se utilice. No sé si esto funciona en tiempo de ejecución ni me importa, la cuestión es que en tiempo de diseño sigo recibiendo el mismo error de recurso no encontrado.
Por lo cual... a la MIERDA. Para salir del paso, usaremos DynamicResource en lugar de StaticResource, lo cual evita el error, pero es algo que yo quería evitar, así que sigo a la espera de una solución. Creo que se lo voy a escribir al chino Zhou, a ver si sabe algo.

P.D. Si el otro día dije que me cargué CommandBinder para integrarlo en las clases que lo necesitaban, finalmente he vuelto a una clase equivalente pero "ehpañola": Gancho. Aunque las causas dan para otra entrada...

Etiquetas: , ,

02 septiembre 2008

Planteamiento final para estilos y temas

Voy a resumir cómo queda finalmente la infraestructura de recursos de nuestra aplicación Precove sobre WPF. Va a tener un bonito soporte para temas. En resumen, cada aplicación incluirá un tema genérico de serie, que luego podrá ser sustituido por otro tema (que podrá venir en una librería externa); este tema no sustituye completamente el tema genérico, sino que redefine los elementos que desee y deja inalterados los que no redefina. Hay involucrados diferentes niveles, así que lo explico mejor por capas:
  1. En la base contamos con dos librerías comunes: Nibi.Presenta y Nibi.Presenta.Temas. En la segunda se ofrece una clase Gestor para aplicar un tema dado (un diccionario de recursos) a una aplicación, basándose normalmente en un tema genérico que la aplicación ofrecerá (si no se proporciona ese tema genérico, el nuevo tema se aplica sobre el tema actual, lo que puede llevar a mezclas curiosas). Además, en esta librería también se ofrece un tema Generico.xaml utilizable en cualquier aplicación y que más bien lo que hace es definir qué claves pueden redefinirse, normalmente sin afectar a la apariencia (sólo con estilos vacíos, o con colores que referencian a los de Windows). Esta definición aparentemente innecesaria sirve para que las referencias StaticResource y DynamicResource no produzcan errores ni advertencias en diseño ni en compilación.
    En Nibi.Presenta se ofrece una serie de comandos básicos, cuyos iconos por defecto se ofrecen en otro diccionario de recursos Iconos.xaml.
  2. En cada librería de interfaz (que nosotros llamamos Forms) se podrán definir los recursos necesarios para visualizar correctamente los elementos de dicha interfaz. Estos recursos contendrán plantillas, estilos, iconos, quizá cadenas e incluso menús de contexto, viniendo a complementar los ofrecidos en Nibi.Presenta.Temas. Cada uno de estos recursos podrá redefinirse posteriormente de forma aislada en un tema personalizado para la aplicación.
  3. En la aplicación se agruparán todos los estilos de sus librerías en un Generico.xaml propio, donde también podrán agregarse (o redefinirse) recursos si fuera necesario. Este será el tema genérico global, el que estará definido en App.xaml y el que se pasará a Gestor para que lo use como base al aplicar un nuevo tema.
  4. En Nibi.Presenta.Temas se ofrecerán más temas, que redefinirán los elementos que define la propia librería, ya que no tendrá conocimiento de los elementos definidos por otras librerías. Así, establecerá elementos como el estilo de los controles comunes (ventanas, botones, cajas de texto...) y una paleta de colores.
  5. Podremos completar los temas básicos ofrecidos con elementos concretos de la interfaz de la aplicación definiendo un tema nuevo que lo extienda, lo que podemos hacer en una librería externa o en la misma aplicación.

El algoritmo de fusión de un nuevo tema con el tema genérico ha sido programado en Gestor (es muy sencillo, pero tiene en cuenta todos los diccionarios que incluye el tema). Al poder fusionar incluso sobre un tema ya aplicado (no siempre sobre el genérico de la aplicación), se abren posibilidades como la de utilizar esta infraestructura para traducir la aplicación, incluyendo los textos de comandos, etiquetas... como recursos que también pueden ser redefinidos. Aunque es un poco engorroso hacer esto ahora, pero to'sandará.

Etiquetas: , , ,