[WPF] Datos en tiempo de diseño (Design-time DataContext)
¡Hola!
Para seguir este artículo necesitaréis de Microsoft Expression Blend 3 o Visual Studio 2010 Beta 2. Además necesitaréis una copia del proyecto del artículo “Data Templates“.
Antes de explicaros qué significa exactamente eso de Datos en tiempo de diseño quiero que veais el problema en vuestras carnes y así buscarle una solución idónea.
Yo usaré Blend 3 así que las imágenes y las instrucciones serán usando este soft, pero se pueden aplicar con Visual Studio 2010 sin ningún problema.
Imaginad esta situación:
Queréis modificar el Data Template que habíamos creado del ejemplo citado. No sé, el borde ese verde que tiene cada item no os gusta y queréis ir probando colores hasta encontrar uno que os guste más. Ningún problema, abres el proyecto con el Blend 3 y….

Vaya tela, nos sale una bonita ventana en blanco… ¿Por qué no sale el contenido? No nos sale porque ni Blend ni Visual studio ni nadie sabe qué ha de representar ahí, o mejor dicho, nosotros estamos ‘bindeando’ ese contenido a una propiedad del DataContext, o sea del ViewModel. Blend no sabe nada sobre ese DataContext que hemos establecido en código, así que el no sabe que ha de mostrar ahi ni nada. Si bien sabe como dibujar el Data Template, no sabe qué ‘Data’ tiene que reprentar ahi.
Entonces con Blend 3 llegó una nueva cosita llamada Datos en tiempo de diseño, o lo que es lo mismo, ofrecerle unos datos ‘de mentira’ a Blend 3 a fin de que los use para dibujar los Data Template en la ventana.
¿Qué quiero decir con eso de ofrecerle unos datos de mentira? Fácil, el ItemsControl está asociado a una lista llamada ListaPersonas, pero dicha lista ‘viene’ del DataContext y como ya os he dicho, el editor visual no puede mostrar nada que venga de ahi, por eso nos aparece la ventana en blanco, porque ignora el DataContext.
Aquí es donde entra el Datos en tiempo de diseño (Design-time Data). es digamos un DataContext especial sólo para diseñar, así podemos mostrar datos ‘Fake’ y ver como quedaría sin ejecutar la aplicación ni nada. Por ejemplo:
Imaginad que estais haciendo una aplicación de Twitter. Cuando la aplicación se conecta a la red, descarga tus tweets, y crea una instancia de la clase Tweet por cada tweet que recoja. ¿Cómo diseñarías la ventana principal del programa? ¿Creas un no sé, ItemsControl y creas un DataTemplate para los Tweet? Es una idea, pero es un coñazo, tienes que crear un template, abrir el programa, conectarte a tu Twitter, que descargue tus Tweets y ver que… oh mierda, ese borde no moooola nada. Cierras la aplicación, modifica el borde y otra vez a probarlo. Si tienes que hacer eso 50 veces para dejar el estilo a tu gusto, mueres.
¿Qué hacer entonces? Creas una clase llamada… FakeTweets por ejemplo que herede de la clase que usa tu ventana de DataContext, ahí instancias la lista del datacontext, creas unos cuantos tweets de mentira y usas la técnica que explicaré a continuación
Este ejemplo es algo muy común, porque donde dices Twitter, dices aplicación de msn y su ventana de contactos, etc.
Vamos a nuestra aplicación que ya está abierta en Blend, y añadimos lo siguiente dentro del Tag de la ventana…
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DataTemplates" mc:Ignorable="d"
Con lo que quedaría así:
<Window x:Class="DataTemplates.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataTemplates"
mc:Ignorable="d"
Title="Data Templates" Height="600" Width="600"
Background="#f8fffb">
Voy a detallar para qué sirve cada uno:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DataTemplates"
Los 3 son namespace como podeis ver, cada uno con una idea en mente.
El primero es el que añade todo el tema de Datos en tiempo de diseño.
El tercero es para importar el namespace de nuestra aplicación (luego veremos por qué)
El segundo va en conjunto con:
mc:Ignorable="d"
El namespace ‘mc’ que hemos importando antes nos sirve para usar el Ignorable. ¿Para qué sirve esto? Sirve para excluir todo lo que sea del namespace indicado a la hora de compilar. ¿Por qué ignoramos el namespace ‘d’? Porque lo que nos ofrece son cosas que nos facilitan la vida a la hora de diseñar la aplicación, pero que a la hora de ejecutarla ya no nos sirve. Así que la aplicación compilada no contendrá nada de lo que coloquemos de cara a ayudarnos a diseñar.
¿Y ahora qué? Ahora tenemos que cargar en el XAML la clase con los datos ‘fake’ (como por ejemplo la clase con tweets de mentira), en nuestro caso nos basta con cargar el Presenter ya que trae datos de ejemplos que nos servirá para el caso.
Para esto podemos usar por ejemplo un ObjectDataProvider:
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:Presenter}" x:Key="FakeVM" />
</Window.Resources>
Como ves, he cargado el Presenter (usando el namespace local que cargué antes) y le he dado el nombre de FakeVM.
Ya solo nos quedaría cargar dicho objeto dentro del Data Context en tiempo de diseño, el cual está en el namcespace ‘d’.
En nuestro ejemplo, se lo asignaremos al ItemsControl como era de esperar:
<ItemsControl ItemsSource="{Binding ListaPersonas}" d:DataContext="{StaticResource FakeVM}">
NOTA: El método que he descrito aquí, inclusive los namespaces de blend, sirve tanto para Blend 3 como para Visual Studio 2010 (Beta 2 en adelante)
ahora, si vamos al modo diseño…
Ya se ve!! Pero dirás… ¿Y ahora qué? ¿Puedo modificar el template en modo diseño y en ver los resultados en tiempo real? Claro que sí!
En Blend 3, abajo a la izquierda nos aparecerá el arbol de objetos de nuestra aplicación:
Ahi hacemos click derecho en ItemsControl y luego Edit Aditional Templates -> Edit Generated Items (ItemTemplate) -> Edit Current. Al hacer esto vemos como se señala el primer objeto del ItemsControl (ya que realmente editando uno, cambian todos).
Ya solo nos queda hacer los cambios pertinentes, por ejemplo cambiando el borde de cada objeto por uno con gradiente Negro <-> Blanco. Comprobareis con alegría que mientras moveis el cursor en la paleta de colores, el resultado se va viendo en tiempo real, y no necesitaréis ejecutar la aplicación con cada cambio.
Así que en resumen, teneis una manera de poder diseñar los Data Templates de forma visual usando datos ‘fake’ y que no afectará para nada a la aplicación compilada.
Espero vuestros comentarios


