[Curso] WPF para programadores de Windows Forms 6

En la última entrega del curso de WPF para programadores de Windows Forms, hablamos de los DataTemplate, que permitían modificar el aspecto visual de un control. Ahora en este articulo vamos a hablar un poco más sobre esta característica y como se puede extender.

Imaginemos por un momento que empezamos a usar esta característica que junto con los estilos permiten modificar el aspecto de un control de una manera muy sencilla, pero que ahora queremos que el usuario, por ejemplo, elija un tema de una lista de temas disponibles. ¿Cómo podríamos encajar esta funcionalidad con los DataTemplate tendríamos que tener algún mecanismo para poder decidir en tiempo de ejecución que DataTemplate tenemos que elegir. Pero la pregunta es cuando hacemos esto ¿cuando el control se ha cargado?, ¿en el constructor?, la respuesta es DataTemplateSelector .

Esta clase, DataTemplateSelector provee una manera de elegir un DataTemplate en tiempo de ejecución, cuando el control se va a enlazar y se va a construir el árbol visual de controles de nuestro elemento.

DataTemplateSelector tiene un método virtual,

public virtual DataTemplate SelectTemplate(Object item, DependencyObject container)

En el que se nos pasa la referencia del objeto de datos el cual el control está enlazado y el control en sí que es pasado en el container. De esta manera y a través de un enlace a datos podemos decidir que DataTemplate tenemos que establecer. Una vez que tenemos una clase que hereda de DataTemplateSelector, y hemos sobreescrito el método SelectTemplate, tenemos que crear una instancia de esta clase y establecerlo en la propiedad ContentTemplateSelector de la clase ContentControl.

Sería algo parecido a esto:

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate

                SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is Task)
            {
                Task taskitem = item as Task;
                Window window = Application.Current.MainWindow;
                if (taskitem.Priority == 1)
                    return
                    window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                    window.FindResource("myTaskTemplate") as DataTemplate;
            }
            return null;
        }
    }
}

Otra necesidad que se nos puede surgir es de generar DataTemplates a partir de código, esto que a priori no es recomendable puesto que añade complejidad extra al código y no permite modificar el aspecto del control a través del xaml y puede que en algún momento sea necesario además de que es necesario recompilar la aplicación.

Si echamos un vistazo a la clase DataTemplate vemos que tiene una propiedad VisualTree, que es el nodo raíz del DataTemplate, el control raíz del DataTemplate. Pero si nos paramos a ver por un momento el tipo de esta propiedad vemos que es de tipo FrameworkElementFactory y no DependencyObjecto Control como podríamos esperar. Esta clase FrameworkElementFactory es en realidad una factoría de FrameworkElement, y es usada por el constructor de controles para inicializar un control. Si nos fijamos en el construcor de esta clase el parámetro que se nos pide es un System.Type que después usara para crear un objeto de ese tipo con System.Activator.

Si miramos los métodos de que dispone esta clase tenemos:

· AddHandler, que nos permite añadir un manejador a un RouteEvent.

· AppendChild, que permite añadir un hijo al elemento actual.

· RemoveHandler, que permite eliminar un manejador previamente creado.

· SetBinding, que permite añadir un binding.

· SetValue, esta es si cabe es el método más interesante de todos ya que nos permite establecer valores de los DP de nuestro control.

En una inicialización normal de un control de WPF podríamos hacer algo así:

Grid grid = new Grid();

Grid.Margin = new Thinkness(3);

Realmente la propiedad Margien es un wrapper en una propiedad del CLR de un DependencyProperty llamado MarginProperty.

Esta sería la manera de hacerla con WPF:

Grid grid = new Grid();

Grid.SetValue(Grid.MarginProperty,new Thinkness(3));

Así que la clase FrameworkElementFactory guarda una lista de los DP que se han establecido para después establecerlos en el control que instancia internamente.

2 comentarios sobre “[Curso] WPF para programadores de Windows Forms 6”

  1. Realmente no existe ningun curso, bueno, es una sucesión de post que estoy escribiendo para intentar solucionar los problemas que se encuentra la gente que viene de Windows Forms o quiere aprender WPF, así que si teneis alguna pregunta, sugerencia o lo que sea.

    Saludos. Luis.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *