[Tip] Tarea de MSBuild + Template de aplicación WPF = Dolor de cabeza

Este post es resultado de un comportamiento extraño que presentaba la aplicación en la que ahora trabajamos. En Plain Concepts utilizamos la metodología SCRUM, por lo que nuestros proyectos siempre cuentan con integración continuas a través de la generación de builds con MSBuild.

Bien, nuestra build generaba un instalador ClickOnce en un servidor Microsoft IIS, solo había que acceder a la dirección del instalador y la aplicación se desplegaba sin problemas. A la hora de ejecutar la aplicación ya desplegada e intentar acceder a cualquiera de los menús, no había ninguna respuesta de la interface gráfica, pero los servicios si eran consumidos y los datos llegaban al cliente. Vamos, que el comportamiento de la aplicación, después de un par de sesiones de debug, era normal, a no ser por el pequeño detalle de que la interface de usuario no hacía nada 😛

Mi compañero J. se dió cuenta que la propiedad Template de los tipos derivados de la clase Control tenía valor null en la aplicación desplegada, mientras que en nuestras máquinas de desarrollo tenía el valor correcto, extraído de Generic.xaml.

Bien, ya tenemos el misterio, ahora vamos a ver quién es el asesino.

Para utilizar las plantillas de Generic.xaml de manera automática hay que cumplir dos condiciones:

  • El fichero Generic.xaml debe de estar colocado en Themes/Generic.xaml
  • El ensamblado debe de estar decorado con el atributo ThemeInfo para indicar dónde se encuentran los diccionarios de recursos. La línea es la siguiente:

[assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)]

Y aquí tenemos al asesino : Para soportar el versionado de ensamblados, una tarea de nuestra build sustituía nuestro AsemblyInfo.cs, por lo que perdíamos la decoración con el atributo necesario. La solución provisional fue indicar explícitamente la ruta al diccionario de plantillas en la sección Application.Resource del fichero App.xaml del proyecto de WPF de la siguiente manera:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source=»Themes/Generic.xaml»/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

 

Una vez detectado el problema, la correción definitiva pasa por que la tarea de MSBuild conserve esa decoración del ensamblado.

La verdad es que ha sido un fallo difícil de localizar, pero en ocasiones venideras creo que es algo que tendremos muy en cuenta… 🙂