[OT] Cambio de Aires

Hola a todos!

Hoy es mi último día de trabajo en mi actual empresa, Intrasoft, a partir del 4 de Noviembre pasaré a formar parte del equipo de Plain Concepts Bilbao!!

Es un cambio brutal en mi vida, dejo en Intrasoft grandes compañeros que me han ayudado a llegar donde estoy hoy, a Victor, Ivan, Ciani, Alberto, Francisco muchas gracias. También dejo un gran jefe, Fran, que me ha ayudado en todo momento. Todos se han convertido en amigos más que compañeros y jefes, y sin duda les extrañaré mucho… a todos GRACIAS AMIGOS!

staré lejos de mi familia durante un tiempo, mi mujer e hijos que me han ayudado en todo este cambio, gr.

Gracias a Rodrigo, Ibon e Iker de Plain Concepts Bilbao por creer en mi y darme esta oportunidad, no os defraudaré!!!!

Plain Concepts Bilbao…. Alla voy!!!!!

Compartiendo Código: Móvil + Web + Escritorio (1/2)

Introducción

Desde hace mucho tiempo, una de las principales preocupaciones de todo programador es la reutilización del código escrito a través de distintos proyectos.

Hasta hace relativamente poco, un proyecto en el que tuviesemos que realizar aplicaciones de escritorio (Windows forms), web (asp.net) y móvil (compact framework) requería reescribir en cada proyecto gran parte de nuestro código, salvando la lógica de negocio y acceso a datos, casi todo lo demás se escribía en exclusiva para cada plataforma.

Con las nuevas tecnologías de desarrollo a nuestro alcance (WPF, Silverlight, Silverlight Mobile) y haciendo uso del patrón MVVM este escenario cambia radicalmente, pudiendo compartir y reutilizar la mayoría de nuestro código entre los distintos tipos de aplicaciones.

A esta reutilización más eficiente de nuestro código debemos añadir el hecho de que, al independizar nuestro código de nuestra capa de visualización, el trabajo de Unit Testing se simplifica en gran manera.

¿Que es MVVM?

MVVM es un patrón de diseño creado por Jhon Grossman, uno de los arquitectos de WPF en Microsoft y desvelado por primera vez en 2005.

Este patrón se compone del Model, la representación de nuestros datos, el ViewModel, un adaptador intermedio que hace nuestro modelo apto para ser consumido por la vista y por último la View, la vista, nuestra capa de presentación.

Gracias al magnífico Binding de WPF / Silverlight este patrón es muy sencillo de usar y en combinación con los comandos, puede reemplazar totalmente a los eventos y desplazar la mayoría del código de la vista al viewmodel, haciéndolo totalmente independiente de la vista en si misma. A continuación tenéis un esquema de esto:

MVVM

Este es un resumen de lo que es MVVM, podéis encontrar una explicación más detallada aquí.

Un ejemplo básico de MVVM

Ahora vamos a ver un ejemplo muy básico de una aplicación MVVM que muestre dos cadenas de texto en una ventana WPF.

Para ello creamos un nuevo proyecto WPF Application, vamos a tener dos clases en este proyecto: BasicModel y BasicViewModel, y vamos a renombrar nuestra ventana MainWindow a BasicView, al terminar deberíamos tener una estructura parecida a esta:

image

Vamos a empezar por definir nuestro modelo, en este caso simplemente tenemos dos métodos públicos que devuelven cadenas de texto y un constructor de clase:

 

 

    class BasicModel
    {
        public BasicModel() { }

        public string SayHello()
        {
            return "Hello Brain";
        }

        public string SayBye()
        {
            return "Bye bye Brain!! (the best WP7 game ever...)";
        }
    }

 

 

Como podéis ver es extremadamente simple, pensad que en el modelo, en vez de devolver simplemente una cadena, consultaríamos la base de datos, etc…

Ahora vamos a por nuestro ViewModel, es muy sencillo también:

 

    class BasicViewModel 
    {
        private BasicModel Model { get; set; }

        public BasicViewModel() 
        {
            Model = new BasicModel();
        }

        public string SayHello
        { 
            get
            {
                return Model.SayHello();
            }
        }

        public string SayBye
        {
            get
            {
                return Model.SayBye();
            }
        }
    }

 

Como podéis ver nuestro ViewModel simplemente actua de intermediario entre nuestra vista final y nuestro modelo, de esta forma conseguimos independizar ambos extremos y nos resultará más sencillo el mantenimiento en ambos puntos.

Finalmente vamos a definir el código xaml que enlazará con nuestro ViewModel para mostrar los datos:

 

<Window x:Class="BasicMVVM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Basic="clr-namespace:BasicMVVM"
        Title="MainWindow" Height="171" Width="285">
        
    <Window.Resources>
        <Basic:BasicViewModel x:Key="BasicVM"></Basic:BasicViewModel>
    </Window.Resources>

    <Grid DataContext="{StaticResource BasicVM}">
        <TextBlock Text="{Binding Path=SayHello}"></TextBlock>
        <TextBlock Text="{Binding Path=SayBye}" Margin="0,27,0,0"></TextBlock>   
    </Grid>
</Window>

 

Simplemente añadimos una referencia al namespace en el que se encuentra nuestra clase ViewModel, creamos con el un recurso de la ventana, usamos el Binding de WPF para establecer nuestro ViewModel como el contexto de datos de la grid y por último enlazamos las propiedades de los textblock a nuestras propiedades.

Y aquí está la mayor virtud de MVVM, como podéis ver, no existe más código en nuestra ventana que el propio xaml para definir los controles y sus bindings, todo el resto del código se encuentra en el Model y el ViewModel, con lo que conseguimos una independencia total de la vista, abriendo el camino hacia la reutilización de nuestro código de una manera más eficiente en diferentes tipos de proyecto.

Si ejecutamos nuestra aplicación veremos que el resultado es el siguiente:

image

 

Conclusiones 1º Parte

Bueno, con esto terminamos la primera parte de este artículo, ya sabemos en líneas generales que es esto del MVVM, de donde viene, las ventajas que aporta y hemos visto un pequeño ejemplo de como usarlo…

En la segunda parte nos centraremos en desarrollar aplicaciones WPF, Silverlight y WP7 que compartan el 80% del código fuente gracias al patrón MVVM.

Espero que os haya resultado entretenido este artículo, a los que ya conocíais MVVM espero que os parezca correcto a los que no lo conocíais espero que os pique la curiosidad por seguir investigando y a todos, muchas gracias por leerme!

Aquí tenéis el código de ejemplo de este artículo, Happy Coding!

Expression Blend 4: Enriqueciendo tus aplicaciones.

Introducción

Cuando Microsoft lanzó oficialmente Silverlight y WPF, se dieron cuenta de que los diseñadores tenían un gran handycap para diseñar usando estas tecnologias: Visual Studio. Visual Studio siempre ha estado dirigido a los desarrolladores y muchos diseñadores no se sentían cómodos usandolo, pues debían lidiar con multitud de elementos que les eran totalmente ajenos.

Para remediar esto, en Junio de 2006 microsoft lanzo una nueva apuesta al mercado: Expression Blend.

Este nuevo software permitía a diseñadores y desarrolladores trabajar juntos en un proyecto Silverlight o WPF, pero cada uno usando una herramienta específica para sus necesidades. De esta forma, Blend, eliminaba todo el contenido superfluo para un diseñador y le permitía centrarse en su trabajo: diseñar.

En estos momentos nos encontramos ya en su versión 4, con el paso de las versiones se ha ido convirtiendo en una herramienta que no podemos ignorar, pues, hasta para los desarrolladores, es muy util para simplificar el trabajo con XAML y dotar de manera rápida y sencilla a nuestras aplicaciones de un aspecto más rico y atractivo.

Interacción

Uno de los puntos fuertes de Blend es la interacción que existe entre este y Visual Studio.

Podemos crear un nuevo proyecto en Visual Studio y después con un simple click de ratón editarlo en Expression Blend, o al reves, crearlo en Expression Blend y editar su código en Visual Studio. Todo de manera sencilla y sin complicaciones, veamos un ejemplo:

1º Abrimos Expression Blend 4 (si no lo tenemos, podemos descargar una demo aquí):

image

Seleccionamos “New Project” y creamos un nuevo proyecto Silverlight Application:

image

En la pestaña de Projects pulsamos con el botón derecho sobre la solución y seleccionamos la opción “Edit in Visual Studio”

Esto abrirá una nueva instancia de Visual Studio en la que podremos trabajar y modificar el proyecto, cuando volvamos a Blend nos advertirá de que se han realizado cambios en el proyecto y nos preguntará si queremos cargar estos cambios.

Con esto podéis ver que la integración entre Visual Studio y Expression Blend es verdaderamente sencilla.

Para ver las ventajas de utilizar Expression Blend en nuestros proyectos, vamos a realizar unos pequeños gráficos para una aplicación Silverlight que servirá como frontend para una pizzeria llamada “PizzaBlend” 🙂

Dibujar en Blend

Personalmente soy partidario de hacer todo el trabajo posible directamente escribiendo XAML pero hay ocasiones en que es bastante complicado o largo de realizar y resulta más productivo usar Blend, para empezar vamos a dibujar una Pizza de pepperoni y aceitnuas (la favorita de mi mujer):

Con el proyecto de Silverlight que hemos creado, vamos a añadir un nuevo usercontrol al mismo, Seleccionando el proyecto y haciendo Click derecho, después seleccionando “Add New Item” nos aparecerá una pantalla con los elementos que podemos añadir al proyecto:

image

Seleccionamos UserControl y cambiamos su nombre a Pizza, presionamos OK y se abrirá el nuevo elemento en Blend.

Seleccionamos la pestaña “Objects and Timeline” que se encuentra al lado de la de proyectos:

image

En esta pestaña tenemos representados todos los elementos que se encuentran el archivo xaml seleccionado, en nuestro caso solo tenemos el userControl y la grid principal llamada LayoutRoot. si seleccionamos UserControl, veremos que en la vista del control aparecen los bordes del mismo con unos puntos y lineas en los bordes derecho e inferior y en la esquina inferior derecha:

image

Bien cada punto y rectángulo ofrecen distinta funcionalidad, los puntos ajustan el tamaño horizontal y vertical de nuestro control, mientras que los rectángulos y la flecha hacen lo mismo pero solo para la vista del diseñador, es decir, si ajustamos el tamaño usando los rectángulos solo lo haremos para la vista de Expression Blend y el tamaño del control se situará en Automático.

También podemos hacer esto con las propiedades que se muestran a la derecha:

image Como podemos ver en esta captura las propiedades Height y Width tienen dos valores Auto y un número, Auto indica que el control no tiene un tamaño fijo definido, el número entre paréntesis indica el tamaño que se muestra en el diseñador, el simbolo image  al lado de cada propiedad indica que la propiedad esta establecida en Auto. Por ahora nos valdrá con establecer estas propiedades en Auto y ajustar el tamaño para el diseñador en 280 de alto por 280 de ancho.

Ahora vamos a diseñar la masa de la Pizza, para esto vamos a añadir un elipse al Usercontrol, esto lo podemos realizar desde la pestaña Assets colocada al lado de la pestaña de proyectos (si no la tenéis podéis mostrarla en el Menu Window –> Assets), En esta pestaña tenemos una lista de varias categorías, una de ellas “Shapes”, la seleccionamos y veremos al lado todas las formas que podemos añadir al proyecto:

image

 

 

Seleccionamos Ellipse y pintamos el elipse sobre el userControl, no importa el tamaño, lo ajustaremos usando un Width y Height Auto y usando los margenes a las esquinas del control para darle un tamaño. Una vez dibujado el elipse, en las propiedades a la derecha verás una propiedad Margin con 4 valores, ajusta los cuatro a 10 pixeles y verás como el elipse se redimensiona, en la parte superior de las propiedades al lado de “Name” escribe Masa.

Para darle color vamos a usar un degradado radial, en la misma pestaña de propiedades de la derecha, en la sección Brushes seleccionamos “Fill”, debajo encontramos varias opciones del tipo de relleno:

image

Nos interesa esta que está seleccionada, la encargada de los degradados, establecemos el degradado como se ve en la siguiente imagen:

image

 

En principio solo nos aparecerán dos puntos de degradado, para añadir más solo debemos pulsar en el lugar de la barra donde queramos añadirlo, para eliminarlo lo seleccionamos con el botón izquierdo y tiramos de el hacia abajo, desaparecerá.

Con esto ya tenemos nuestra masa, no tiene una pinta muy interesante por ahora, pero mejorará, algo al menos… espero… soy programador, comprendedme jeje.

Ahora añadimos un segundo elipse al user control, establecemos su margen en 30 píxeles y como relleno le establecemos este degradado radial:

image

En este caso también seleccionamos la Brush “Stroke” y le aplicamos un color rojo solido con un Alpha del 33%:

image

Bien, con esto nuestra pizza ya tiene otro aspecto, pero el borde entre el segundo y el primer elipse es muy evidente, vamos a usar un efecto de desdibujado para “maquillarlo un poco”,seleccionamos el elipse que acabamos de crear, seleccionamos de nuevo la pestaña “Assets” y esta vez seleccionamos el elemento “Effects”, seleccionamos el efecto BlurEffect y lo arrastramos sobre nuestro segundo elipse, en las propiedades le aplicamos un radio de 9 pixeles.

Bueno, ahora ya solo queda ponerse creativo con los ingredientes, esto lo dejo a vuestro parecer, pero básicamente el resultado es algo como esto:

image

Ahora ya tenemos nuestra pizza, de plastico… y no demasiado apetecible… pero nuestra al fin y al cabo. ¿Por que no le damos algo de movimiento?

Animación en Blend

Vamos a realizar una sencilla animación a nuestra pizza que la haga rotar indefinidamente, gracias a Blend las animaciones son muy sencillas de realizar y a cambio le otorgan a nuestra aplicación mucho dinamismo.

En la pestaña de “Objects and Timeline” seleccionamos “LayoutRoot” y creamos una nueva animaciíon presionando el simbolo + que se encuentra bajo la pestaña:

image

 

 

Establecemos el nombre de la animación en la ventana emergente y presionamos OK:

image

Y en este momento aparece la “magia” de blend para las animaciones, un marco rojo aparecerá en nuestra vista de diseño junto con la indicación “PizzaRotation timeline recording is on” y una linea de tiempo al lado de nuestras pestañas izquierdas:

image

En este momento y hasta que presionemos el botón redondo rojo al lado de “PizzaRotation timeline recording is on” todos los parámetros y propiedades que toquemos serán animados en el tiempo. desplazando la línea de tiempo amarilla estableceremos los KeyFrames donde cada propiedad cambiará de valor, esto es si la rotación del LayoutRoot en el segundo 0 es 0, y movemos la línea amarilla hasta el segundo 3, y acto seguido rotamos el LayoutRoot 360º, automáticamente Silverlight mostrará una animación de 3 segundos con nuestra pizza rotando 360º.

La animación tiene varias propiedades:

imageAutoreverse causará que, al terminar, la animación se reproduzca automáticamente en sentido inverso hasta llegar al comienzo.

RepeatBehavior: Nos permite indicar cuantas veces se debe repetir la animación, si indicamos Forever siempre estará reproduciendose.

Bien ahora solo nos queda indicar a la animación que comience a reproducirse cuando nosotros queramos, en este caso esto será cuando se dispare el evento Loaded del UserControl.

En la pestaña “Objects and Timeline” seleccionamos el userControl y en las propiedades pulsamos el botón eventos al lado del nombre:image .

Con esto veremos una lista de los eventos que soporta el UserControl, entre ellos veremos el evento Loaded, hacemos doble click sobre la caja de texto vacía a su lado y nos crea por defecto el manejador de eventos para Loaded, al que añadiremos el código que inicia la animación:

image

 

Bien, ahora solo tenemos que incorporar el userControl a una página de silverlight para que funcione.

Lo primero que necesitamos es compilar todo el proyecto para que nuestro usercontrol pase a formar parte de nuestro ensamblado. Esto lo podemos realizar desde el menu “Project” en la opción “Rebuild Project”

Una vez hecho esto, seleccionamos en la pestaña “Projects” el archivo MainPage.xaml y hacemos doble click sobre el para que  se abra en el editor, nos vamos a la pestaña “Assets” y seleccionamos el elemento “Project”, en el deberemos encontrar el UserControl1, nuestra pizza, simplemente debemos arrastrarlo hasta el formulario y podremos verlo.

Si ejecutamos el proyecto usando la tecla “F5” o la opción Run del menú “Project” veremos que nuestra pizza rota indefinidamente.

Básicamente la animación en Blend no tiene muchos más secretos y esto es lo mejor de todo, en el proyecto adjunto he añadido algunas animaciones más jugando con efectos en la animación para que podáis practicar por vosotros mismos:

image

P.D.: Espero que mis habilidades de diseño no hayan herido la sensibilidad de ningún diseñador, si es así, creedme, no ha sido mi intención 🙂

Espero que os haya gustado, ya sabéis, espero vuestros comentarios 🙂

Un gran saludo y Happy Coding!

WP7: Acceso a la información de Licencia y Al Marketplace desde nuestra aplicación.

Ahora que se acerca la apertura del marketplace para Windows Phone 7 es hora de ir dando los últimos toques a nuestras aplicaciones e ir preparándolas para el gran público.
Algo muy importante para que nuestra aplicación tenga buena acogida entre los usuarios es que estos sean capaces de probarla y verla en funcionamiento antes de tener que invertir su dinero en ella, quizás incluso sería interesante el poder ofrecer a los usuarios una versión gratuita de nuestra aplicación para que la probasen, que tuviese todas las características de la versión de pago y sin limitaciones, usando publicidad para ganar algo de dinero con esta versión y ofreciendo al usuario eliminar esta publicidad comprando la versión de pago.

Tradicionalmente en otras plataformas para aplicaciones móviles de la “competencia” la forma de realizar esto pasaba por crear versiones “Lite” de nuestra aplicación que eran subidas como una aplicación independiente, duplicando de esa forma el esfuerzo necesario para realizar el mantenimiento de nuestra aplicación y duplicando el numero de aplicaciones en la tienda en cuestión.
Microsoft ha resuelto esto, como de costumbre, de forma rápida, elegante y sencilla.

El namespace Microsoft.Phone.Marketplace

Este namespace se encuentra en el ensamblado Microsoft.Phone y en estos momentos expone solo una clase: LicenseInformation.
Esta clase LicenseInformation expone un sólo método: IsTrial, el cual devuelve un valor boolean indicando si nuestra aplicación se encuentra en modo de prueba o no.
Pero…. ¿Como sabe esto el teléfono? Bueno, el sistema que usan en microsoft para instalar la aplicación en un dispositivo y validar que proceda del marketplace hace posible la magia:
Cuando el usuario accede a los detalles de nuestra aplicación en el marketplace se le presenta la opción de “probarla” o “comprarla”, en cualquiera de los dos casos la aplicación descargada es la misma, pero el certificado de seguridad que se descarga es distinto, en el caso de que la compre, se descarga el certificado real de la aplicación, sin embargo si se descarga una “prueba” el certificado que obtenemos es un certificado de pruebas, De esta forma examinando este certificado podemos saber en que estado se encuentra nuestra aplicación, y una vez que el usuario acabe de probar y decida comprar, no debe descargar de nuevo toda la aplicación, tan solo obtendrá el certificado real y la aplicación empezará a funcionar de forma completa.
Bien, como puedes ver es muy sencillo y transparente tanto para el desarrollador como para el usuario. Para implementar este comportamiento solo debemos comprobar cuando nos interese la respuesta del método IsTrial en la clase LicenseInformatión, Por ejemplo podríamos llamar a este método en los eventos Launching y Activated de nuestra aplicación y guardar el resultado en una variable global que nos permita consultarla desde cualquier punto de la aplicación de forma sencilla:
Primero definimos nuestra variable en la clase App:
public partial class App : Application
{
public static Boolean DemoMode = false;
}

En el evento Launching, que se ejecuta cuando la aplicación se abre desde 0, sin que haya sido desactivada por otro programa o por el usuario, comprobamos en que modo nos encontramos:

// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
//Comprobamos si nos encontramos en modo demo.
Microsoft.Phone.Marketplace.LicenseInformation InfoLicencia;
InfoLicencia = new Microsoft.Phone.Marketplace.LicenseInformation();
//Establecemos si nos encontramos en modo demo.
DemoMode = InfoLicencia.IsTrial();
}

Y en el evento Activated, que se ejecuta cuando la aplicación se abre después de ser desactivada por otro proceso o por el usuario, comprobamos en que modo nos encontramos de nuevo:

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
//Comprobamos si nos encontramos en modo demo.
Microsoft.Phone.Marketplace.LicenseInformation InfoLicencia;
InfoLicencia = new Microsoft.Phone.Marketplace.LicenseInformation();
DemoMode = InfoLicencia.IsTrial();
}

Y con esto, en nuestro código ya solo tendremos que comprobar el valor de la propiedad DemoMode de la clase App para saber si debemos mostrar la publicidad, limitar el numero de items de algunas listas, pedirle al usuario que nos ayude a llegar a fin de mes o la estrategia que queramos seguir para mostrar y vender nuestra aplicación.

Bien, ya sabemos como convertir nuestra aplicación en una demo de forma automática, pero…. ¿como hacemos para ayudar al usuario a comprar nuestra aplicación? Bien, aquí entra en juego uno de los Launchers de WP7: el MarketplaceDetailTask.

El launcher MarketplaceDetailTask

Espera, espera…. ¿Por las barbas de mi abuelo…..que es un launcher? Bien, es muy común el caso en el que queramos hacer uso de funcionalidad del propio sistema operativo, como puede ser hacer una llamada, enviar un email o sms, abrir el navegador web y algunas cosas más. Esto lo podemos realizar mediante un Api que expone el sistema, localizada en el namespace Microsoft.Phone.Tasks. Hay dos tipos de tareas, las que lanzan una característica del teléfono, como por ejemplo enviar un email, y no devuelven nada a nuestra aplicación se llaman Launchers y las que lanzan una característica del teléfono y devuelven un resultado, como por ejemplo seleccionar una imagen del HUB de imágenes, que se llaman Choosers.

Una vez aclarado esto, existe un Launcher llamado MarketplaceDetailTask que nos permite abrir desde nuestra aplicación el Hub del marketplace del sistema en los detalles de una aplicación específica.

Esta clase tiene dos propiedades principales: ContentType y ContentIdentifier:

 

  • ContentType indica el tipo de contenido que podemos mostrar, se le asigna un valor del enumerador Microsoft.Phone.Tasks.MarketplaceContentType, que puede ser Applications o Music.
  • ContentIdentifier indica el ID único del marketplace de la aplicación que queremos mostrar, si queremos mostrar los detalles de nuestra propia aplicación bastará con pasarle un valor nulo.

Por último, solo debemos usar el método Show de la clase MarketplaceDetailTask para que nuestra aplicación se desactive y se muestre el marketplace con nuestros detalles.

El código quedaría así:

 

Microsoft.Phone.Tasks.MarketplaceDetailTask Detalles;
Detalles = new Microsoft.Phone.Tasks.MarketplaceDetailTask();
Detalles.ContentType = Microsoft.Phone.Tasks.MarketplaceContentType.Applications;
Detalles.ContentIdentifier = App.AppUniqueID;
Detalles.Show();

 

Conclusión

Y con esto terminamos este artículo, Como siempre os dejo un pequeño proyecto de ejemplo con todo lo que hemos visto aplicado, para que podáis probarlo, tened en cuenta que el marketplace os dirá que no se puede acceder en estos momentos, pues todavía no está disponible para su uso.

Podéis contactar conmigo por mi correo, por Twitter, aquí dejando un mensaje o incluso en los foros de Silverlight / WPF de MSDN por los que siempre ando. Estaré encantado de resolver cualquier duda que tengáis (sobre esto… el sentido de la vida no me dejan revelarlo) y charlar un rato con vosotros.

Muchas gracias por leerme, sin todos vosotros estas palabras no tendrían sentido de existir.

Un gran saludo y Happy Coding!

WPF: Arboles

Hola a todos

Los elementos de la interface de usuario de una aplicación WPF tienen una relación jerárquica, esta relación toma el nombre de Object Tree, un árbol en el que podemos encontrar todos los objetos anidados que tenemos en nuestra aplicación.
El Object Tree es más un concepto o metáfora que una realidad, pues ciertas propiedades y comportamientos de controles pueden romper esta vista de árbol en tiempo de ejecución. Para evitar esto WPF expone dos arboles distintos que pueden ser accedidos por nuestra aplicación: Logical Tree y Visual Tree.

 

En el gráfico anterior podéis ver el árbol de objetos (Object Tree) de una ventana WPF, y como podemos subdividirlo entre el árbol lógico y el árbol visual
Como sabéis un control en WPF se compone en su forma visual de una plantilla que contiene los controles que dan forma a nuestro control, el Object Tree de WPF contiene información de cada control que tenemos en nuestra ventana, sus hijos y los controles que lo componen en su plantilla.

Logical Tree

El árbol lógico de una ventana en WPF contiene información acerca de la organización jerárquica de los controles en la misma, tendremos normalmente un Objeto Window como principio del árbol del cual se desprenderán de forma ordenada el resto de controles que componen la ventana, tal y como los hayamos definido en código o en Xaml.
El propósito principal de este árbol lógico es el de ofrecer en tiempo de ejecución una representación veraz y realista de nuestros objetos de forma que podamos consultarlos sin preocuparnos de los controles que componen a cada uno, por ejemplo para poder buscar un control de un cierto tipo dentro de nuestra ventana sin tener que recorrer los controles que componen la visualización:
<RichTextBox>
<FlowDocument>
<Paragraph>
Hola <Rectangle Width='10' Height='10' Fill='Red' />
</Paragraph>
</FlowDocument>
</RichTextBox>

Si miramos el Xaml escrito aquí, veremos que tenemos un control Rectangle dentro de un Paragraph que a su vez se encuentra en un FlowDocument, contenido por un RichTextBox. Así si queremos obtener el Padre lógico del control rectangle este será el control Paragraph pues es quien lo contiene. Esta secuencia es la que nos devolvería el Logical Tree, más adelante veremos este mismo ejemplo con el Visual Tree para observar las diferencias entre ambos.

Este es un ejemplo del resultado de recorrer el árbol lógico del Xaml que tenemos arriba:

image

 

Visual Tree

El árbol visual de una ventana WPF contiene información acerca de los controles representados gráficamente en la misma. De esta forma, siguiendo el ejemplo anterior de la Ventana, y como podemos ver en el gráfico anterior, de la Ventana no se desprenderá directamente el contenido de la misma, primero tendremos los controles que componen la plantilla de la ventana y bajo el contentpresenter de la misma encontraremos el resto de controles, junto a su composición interna.

El propósito principal de este árbol visual es el de ofrecer una relación de TODOS los controles dibujados en nuestra ventana, sin distinguir entre controles insertados en la ventana y los controles que componen a estos como puede ser el Border, ContentPresenter y los demás, examinemos el ejemplo anterior:

 

<RichTextBox>
<FlowDocument>
<Paragraph>
Hola <Rectangle Width='10' Height='10' Fill='Red' />
</Paragraph>
</FlowDocument>
</RichTextBox>

En este caso, si queremos obtener el Padre visual de nuestro rectangle usando el árbol visual este nos devolverá como control padre el RichTextBox, en vez del Paragraph, pues los controles Paragraph, FlowDocument, etc… son considerados elementos inline y no controles. Este es un ejemplo del resultado de recorrer el árbol visual del Xaml que tenemos arriba:

image 

 

Diferencias entre Logical Tree y Visual Tree

Como podéis existen grandes diferencias entre el Árbol Lógico y Visual, y sin duda dependiendo de la situación nos será útil recorrer uno u otro, pero, ¿Cuando usar cada uno? Aquí tenéis las principales características de cada uno:

  • Logical Tree:
    • Responsable de la herencia de valores de las DependencyProperties
    • Resuelve referencias a DynamicResources
    • Busqueda de Nombre de elementos para Binding
    • Pasar RoutedEvents a ancestros.
  • Visual Tree:
    • Dibujado de elementos Visuales
    • Propagación de opacidad de elementos
    • Propagación de LayoutTransform y RenderTransform
    • Propagación de la propiedad IsEnabled
    • Hit Testing
    • RelativeSource (FindAncestor)

     

Conclusión

Para poder trabajar con estos arboles disponemos de dos clases en WPF: VisualTreeHelper y LogicalTreeHelper que nos ofrecen métodos para movernos en el árbol de cada uno de forma sencilla, Como ejemplo os dejo dos métodos recursivos que recorren el árbol lógico y el visual añadiendo a un treeview todas las ocurrencias a partir de un control dado:

'Obtenemos todos los controles hijos visuales del control base indicado.
Private Sub Recursive_GetVisualChildrens(ByVal BaseControl As DependencyObject,
ByVal ParentNode As TreeViewItem)
If VisualTreeHelper.GetChildrenCount(BaseControl) > 0 Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(BaseControl) - 1
Dim Hijo As New DependencyObject()
Hijo = VisualTreeHelper.GetChild(BaseControl, i)
Dim Nodo As New TreeViewItem
Nodo.Header = Hijo.DependencyObjectType.Name
Recursive_GetVisualChildrens(Hijo, Nodo)
ParentNode.Items.Add(Nodo)
Next
End If
End Sub

'Obtenemos todos los controles hijos lógicos del control base indicado.
Private Sub Recursive_GetLogicalChildrens(ByVal BaseControl As DependencyObject,
ByVal ParentNode As TreeViewItem)
For Each Hijo As Object In LogicalTreeHelper.GetChildren(BaseControl)
Dim Nodo As New TreeViewItem
Nodo.Header = Hijo.GetType().Name
Try
Recursive_GetLogicalChildrens(CType(Hijo, DependencyObject), Nodo)
Catch ex As Exception
End Try
ParentNode.Items.Add(Nodo)
Next
End Sub

Y como ayuda y demostración os dejo una aplicación WPF que hace uso de estos métodos para que juguéis con ella:

image

 

Espero que os haya gustado tanto leer este artículo como a mi escribirlo.

 

Por si tenéis alguna dificultad, a parte por supuesto de poder contactar conmigo tanto dejando mensajes, como en mi twitter, como en msdn o a mi email directamente, os dejo el proyecto completo para descarga.

 

Y recordad, con un simple comentario, podéis hacer feliz a un pequeño bloguero 🙂

 

Muchas gracias por leerme y Happy Coding!

Estrenandome en Geeks.ms

Hola a todos!

Ayer Rodrigo Corral me dió la gran oportunidad de unirme a esta comunidad.

Hasta ahora escribía mi blog sobre tecnología en http://jyeray.blogspot.com, a partir de ahora intentare mantener ambos.

Espero poder ayudar a que la gente que se está introduciendo en este mundo que es .NET tengan los conceptos claros y aprendan como hacer las cosas bien y de forma efectiva.

Un gran saludo a todos y Happy Coding!