Windows Phone. Coding4Fun MemoryCounter.

Una vez finalizado el desarrollo de nuestra aplicación para Windows Phone desearemos publicarla en el MarketPlace. Para ello, debe pasar un proceso de certificación donde se le realizarán múltiples pruebas que debe superar con éxito. Uno de los puntos vitales a tener en cuenta durante la fase de desarrollo es el rendimiento. Hoy nos centraremos en la gestión de memoria.

NOTA: En Windows Phone Mango el límite de consumo de memoria por parte de la aplicación eran 90MB, en Windows Phone Tango, el límite  baja a los 60MB.

Para ello, utilizaremos el control Memory Counter disponible en el Conding4Fun Toolkit (totalmente gratuito, hablamos  del toolkit en esta entrada). El control Memory Counter permite monitorear el uso total de memoria de nuestra aplicación de manera muy fácil (algo vital a hacer para llegar a buen puerto en la certificación de la misma).

Vamos a realizar un ejemplo práctico para entender mejor que nos aporta el control y como aprovechar todas sus posibilidades. Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo.

Para poder utilizar el control MemoryCounter lo primero que debemos hacer es añadir la referencia a la siguiente librería:

Coding4Fun.Phone.Controls.dll

Nos centramos en la página principal (MainPage.xaml). Añadimos el siguiente namespace:

xmlns:Coding4Fun="clr-namespace:Coding4Fun.Phone.Controls;assembly=Coding4Fun.Phone.Controls"

Ya podemos utilizar el control. Es tán sencillo como añadir:

<Coding4Fun:MemoryCounter/>

Si compilas en este momento podrás ver al control en acción:

NOTA: El control MemoryCounter sólo funciona en modo DEBUG.

Centremonos a continuación en las propiedades principales del control:

  • UpdateInterval. Propiedad de dependencia de tipo Int. Indica cada cuanto se refresca la información proporcionada por el control. Por defecto el valor es 1000.
  • CurrentMemory. Propiedad de dependencia de tipo String. Representa el consumo de memoria actual por la aplicación.
  • PeakMemory. Propiedad de dependencia de tipo String. Representa el pico máximo de memoria alcanzado por la aplicación en algún momento.
<Coding4Fun:MemoryCounter x:Name="memoryCounter" UpdateInterval="250" Foreground="Red"/>

Vamos a añadir una serie de botones que nos permita “jugar” con la memoria utilizada para poder probar el control MemoryCounter:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <Coding4Fun:MemoryCounter x:Name="memoryCounter" UpdateInterval="250" Foreground="Red"/>
     <StackPanel VerticalAlignment="Center">
          <Button x:Name="btnLoad" Content="Cargar 10MB en Memoria"/>
          <Button x:Name="btnClear" Content="Limpiar Memoria"/>
          <Button x:Name="btnInfo" Content="Ver uso de Memoria" Margin="0,150"/>
     </StackPanel>
</Grid>

Hemos añadido tres botones. El primero de ellos sumará cada vez que se pulse 10MB más a la memoria usada, el segundo limpiará la memoria añadida por el primero botón y por último el tercer botón nos permite consultar el uso de memoria.

Añadimos los eventos Click de cada botón:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <Coding4Fun:MemoryCounter x:Name="memoryCounter" UpdateInterval="250" Foreground="Red"/>
     <StackPanel VerticalAlignment="Center">
          <Button x:Name="btnLoad" Content="Cargar 10MB en Memoria" Click="btnLoadClick"/>
          <Button x:Name="btnClear" Content="Limpiar Memoria" Click="btnClearClick"/>
          <Button x:Name="btnInfo" Content="Ver uso de Memoria" Click="btnInfoClick" Margin="0,150"/>
     </StackPanel>
</Grid>

Creamos una colección de Bytes para cargar en memoria:

List<Byte[]> _memoria;

// Constructor
public MainPage()
{
     InitializeComponent();

     _memoria = new List<byte[]>();
}

En el primer botón añadimos 10MB al uso de memoria. En el segundo, limpiamos la colección y llamamos el recolector de basura:

private void btnLoadClick(object sender, RoutedEventArgs e)
{
     _memoria.Add(new Byte[1024 * 1024 * 10]);
}

private void btnClearClick(object sender, RoutedEventArgs e)
{
     _memoria.Clear();
     GC.Collect();
}

Por último, utilizaremos las propiedades CurrentMemory y PeakMemory del control MemoryCounter para mostrarselas al usuario en un mensaje al pulsar el botón:

private void btnInfoClick(object sender, RoutedEventArgs e)
{
     string mensaje = string.Format("Memoria usada actualmente: {0}Mb" + Environment.NewLine + "Memoria máxima que se ha llegado a utilizar: {1}Mb", memoryCounter.CurrentMemory, memoryCounter.PeakMemory);
     MessageBox.Show(mensaje);
}

Puedes ver en video el ejemplo realizado a continuación:

También puedes descargar el ejemplo realizado:

Nada más en esta entrada. Hemos visto un control bastante interesante y sobretodo muy útil. Os recomiendo que lo probéis. Si os surgen dudas o sugerencias podéis dejarlas en los comentarios.

Más información:

Windows Phone. Control MetroFlow.

En esta entrada vamos a analizar todas las posibilidades que podemos encontrar en el control MetroFlow. El control MetroFlow forma parte del conjunto de controles ofrecidos por el Condin4Fun Toolkit del que hablamos en esta entrada.

El control MetroFlow nos permite crear de manera muy rápida y sencilla pequeñas galerías de imágenes. Todas las imágenes de la galería estarán siempre contraidas excepto una. A continuación, puedes ver una captura donde podemos comenzar a hacernos una idea de su estructura.

Vamos a realizar un ejemplo práctico para entender mejor que nos aporta el control y como aprovechar todas sus posibilidades. Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo.

Agregamos dentro del Grid principal de la página MainPage.xaml:

<!--ContentPanel. Colocar aquí el contenido adicional-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
          <Button x:Name="btnSimple" Content="Más simple"/>
          <Button x:Name="btnPropiedadesXAML" Content="Propiedades desde XAML"/>
          <Button x:Name="btnPropiedadesCB" Content="Propiedades desde Code Behind"/>
          <Button x:Name="btnEventos" Content="Eventos"/>
          <Button x:Name="btnPersonalizacion" Content="Personalización"/>
     </StackPanel>
</Grid>

Conseguiremos la siguiente interfaz:

Vamos a añadir el manejador del evento Click de cada uno de los botones:

<!--ContentPanel. Colocar aquí el contenido adicional-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
          <Button x:Name="btnSimple" Content="Más simple" Click="btnSimple_Click"/>
          <Button x:Name="btnPropiedadesXAML" Content="Propiedades desde XAML" Click="btnPropiedadesXAML_Click"/>
          <Button x:Name="btnPropiedadesCB" Content="Propiedades desde Code Behind" Click="btnPropiedadesCB_Click"/>
          <Button x:Name="btnEventos" Content="Eventos" Click="btnEventos_Click"/>
          <Button x:Name="btnPersonalizacion" Content="Personalización" Click="btnPersonalizacion_Click"/>
     </StackPanel>
</Grid>

Al pulsar sobre cada uno de los botones llevaremos al usuario a una nueva página por lo que necesitamos antes que nada añadir al proyecto las 5 páginas necesarias que utilizaremos. En el ejemplo que podéis descargar al final de la entrada se añadieron 5 páginas llamadas:

  • Simple
  • PropiedadesXAML
  • PropiedadesCodeBehind
  • Eventos
  • Personalizacion

A continuación, vamos a ver que se hace en cada uno de los botones.

private void btnSimple_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/MetroFlow/Simple.xaml", UriKind.Relative));
}

private void btnPropiedadesXAML_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/MetroFlow/PropiedadesXAML.xaml", UriKind.Relative));
}

private void btnPropiedadesCB_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/MetroFlow/PropiedadesCodeBehind.xaml", UriKind.Relative));
}

private void btnEventos_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/MetroFlow/Eventos.xaml", UriKind.Relative));
}

private void btnPersonalizacion_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/MetroFlow/Personalizacion.xaml", UriKind.Relative));
}

Nada fuera de lo común. Utilizamos el servicio de navegación NavigationService para enviar al usuario a la página correspondiente. Puedes ver todo lo relacionado con el servicio de navegación NavigationService en esta entrada.

Dado que el control forma parte del conjunto de controles disponibles en el Coding4Fun SDK, debemos agregar la referencia a la librería Coding4Fun.Phone.Controls.dll. Tras añadir la librería podemos incluir en las páginas que acabamos de crear:

xmlns:c4f="clr-namespace:Coding4Fun.Phone.Controls;assembly=Coding4Fun.Phone.Controls"

Vamos a centrarnos en la primera de las páginas donde realizaremos el ejemplo más sencillo de todos:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <c4f:MetroFlow>
          <c4f:MetroFlowData Title="Item 1" />
          <c4f:MetroFlowData Title="Item 2" />
          <c4f:MetroFlowData Title="Item 3" />
          <c4f:MetroFlowData Title="Item 4" />
          <c4f:MetroFlowData Title="Item 5" />
     </c4f:MetroFlow>
</Grid>

Como puedes ver en el primer ejemplo añadimos tantas instancias de MetroFlowData como elementos deseamos tener. Veamos las propiedades básicas correspondientes al MetroFlowData:

  • ImageUri.  Propiedad de dependencia de tipo Uri. Es la imágen correspondiente al elemento.
  • Title. Propiedad de dependencia de tipo String. Es el texto que aparecerá en la parte inferior del elemento.

En este primer ejemplo hemos establecido la propiedad Title pero no la propiedad ImageUri. Sencillamente los elementos no cuentan con imágen.

¿Existe un número máximo de elementos?

No. Podemos añadir tantos como necesitemos. Sin embargo, ten en cuenta que a más elementos más pequeño es el ancho de cada elemento contraido dificultando la interacción adecuada por parte del usuario. Recomendaría utilizar un máximo de 6 elementos en total.

Veamos el código utilizado en la página “PropiedadesXAML”:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<c4f:MetroFlow>
<c4f:MetroFlowData ImageUri="../IMGS/Lumia610.jpg" Title="Nokia Lumia 610"/>
<c4f:MetroFlowData ImageUri="../IMGS/Lumia710.jpg" Title="Nokia Lumia 710"/>
<c4f:MetroFlowData ImageUri="../IMGS/Lumia800.jpg" Title="Nokia Lumia 800"/>
<c4f:MetroFlowData ImageUri="../IMGS/Lumia900.jpg" Title="Nokia Lumia 900"/>
</c4f:MetroFlow>
</Grid>

En este caso hemos utilizado en cada elemento las propiedades Title e ImageUri.

Nota: En el ejemplo anterior hace uso de varias imágenes. Para ello se ha añadido una carpeta “IMGS” en el proyecto donde hemos añadido las imágenes utilizadas. Las imágenes utilizadas en el ejemplo las puedes ver a continuación:

Hasta ahora en todos los ejemplos realizados definimos en control MetroFlow con sus elementos en el XAML pero … ¿Es obligatorio?.

Para nada. Como cualquier control podemos trabajar con el desde el code behind de la aplicación. En el tercer ejemplo que vamos a ver a continuación veremos como hacerlo:

//Creamos el MetroFlow dinamicamente:
Coding4Fun.Phone.Controls.MetroFlow metroFlow = new Coding4Fun.Phone.Controls.MetroFlow();

// Añadimos cada MetroFlowData:
metroFlow.Items.Add(new MetroFlowData { Title = "Nokia Lumia 610", ImageUri = new Uri(@"..\IMGS\Lumia610.jpg", UriKind.RelativeOrAbsolute) });
metroFlow.Items.Add(new MetroFlowData { Title = "Nokia Lumia 710", ImageUri = new Uri(@"..\IMGS\Lumia710.jpg", UriKind.RelativeOrAbsolute) });
metroFlow.Items.Add(new MetroFlowData { Title = "Nokia Lumia 800", ImageUri = new Uri(@"..\IMGS\Lumia800.jpg", UriKind.RelativeOrAbsolute) });
metroFlow.Items.Add(new MetroFlowData { Title = "Nokia Lumia 900", ImageUri = new Uri(@"..\IMGS\Lumia900.jpg", UriKind.RelativeOrAbsolute) });

// Indicamos el MetroFlowData que estará expandido:
metroFlow.SelectedColumnIndex = 3;

//Añadimos el control al Grid principal de la página:
ContentPanel.Children.Add(metroFlow);

Visualmente el resultado final conseguido es exactamente el mismo que en el ejemplo anterior (te invito a comparar el código utilizado en cada uno de ellos para lograr el mismo resultado). Lo único a destacar en el ejemplo es la propiedad SelectedColumnIndex. Es una propiedad de dependencia de tipo entero (int) que utilizamos para indicar el elemento que estará expandido. El control MetroFlow cuenta con más propiedades  entre las que destacamos la siguiente:

  • AnimationDuration. Propiedad de dependencia de tipo TimeSpan. Determina el tiempo que durará la animación que se ejecuta cada vez que cambiamos de elemento.

Hasta ahora hemos visto la estructura, definición y las propiedades básicas del control. Sin embargo, puedes estar preguntandote … ¿Que eventos podemos llegar a necesitar?.

En ese punto en concreto nos detendremos en el siguiente ejemplo (Eventos). Veamos primero la definición de la interfaz:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <c4f:MetroFlow SelectionChanged="MetroFlow_SelectionChanged" SelectionTap="MetroFlow_SelectionTap">
          <c4f:MetroFlowData ImageUri="../IMGS/Lumia610.jpg" Title="Nokia Lumia 610"/>
          <c4f:MetroFlowData ImageUri="../IMGS/Lumia710.jpg" Title="Nokia Lumia 710"/>
          <c4f:MetroFlowData ImageUri="../IMGS/Lumia800.jpg" Title="Nokia Lumia 800"/>
          <c4f:MetroFlowData ImageUri="../IMGS/Lumia900.jpg" Title="Nokia Lumia 900"/>
     </c4f:MetroFlow>
</Grid>

Como podemos ver en el ejemplo anterior hacemos uso de dos eventos:

  • SelectionChanged. Este evento ocurre cuando el elemento seleccionado cambia.
  • SelectionTap. Este evento ocurre cuando se pulsa sobre un elemento (Tap).

Veamos los manejadores de dichos eventos:

private void MetroFlow_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
     MessageBox.Show("Este evento se dispara cada vez que se cambia de item.");
}

private void MetroFlow_SelectionTap(object sender, Coding4Fun.Phone.Controls.SelectionTapEventArgs e)
{
     MessageBox.Show(string.Format("Este evento se dispara cuando se pulsa sobre un item en concreto. Item pulsado: {0}", e.Data.Title));
     //Hay más propiedades de interés en el SelectionTapEventArgs como: e.Data.ImageUri
}

Hasta ahora hemos utililizado el control sin preocuparnos de su visualización (forma o colores). Sin alterar nada se consigue un resultado bastante atractivo visualmente. Sin embargo, ¿qué podemos hacer si no nos convence?

Podemos modificar su estilo para adaptarlo visualmente a nuestras necesidades. Hablaremos de recursos, estilos, plantillas, etc. con muchísima profundidad en próximas entradas. De momento, veremos que debemos hacer para modificar el control visualmente.

Debemos definir los recursos a utilizar(de forma breve podemos indicar que son trozos de XAML a los que les podemos poner un identificador para poder reaprovecharlos posteriormente). Para ello, en nuestra página podemos utilizar la colección Resources para especificarlos.

<phone:PhoneApplicationPage.Resources>
</phone:PhoneApplicationPage.Resources>

A continuación, dentro de la colección de recursos definimos:

<Style x:Key="MetroFlowItemTextBlockStyle" TargetType="TextBlock">
     <Setter Property="FontSize" Value="18" />
     <Setter Property="Margin" Value="12, 3, 0, 3" />
     <Setter Property="HorizontalAlignment" Value="Left" />
     <Setter Property="VerticalAlignment" Value="Bottom" />
</Style>

<Style x:Key="MetroFlowItemRectangleUnderlay" TargetType="Rectangle">
     <Setter Property="Fill" Value="Yellow" />
     <Setter Property="Margin" Value="0, -.5" />
     <Setter Property="Opacity" Value=".6" />
</Style>

<Style x:Key="MetroFlowItemImage" TargetType="Image">
     <Setter Property="Margin" Value="0, -.5, 0, 0" />
     <Setter Property="Stretch" Value="UniformToFill" />
     <Setter Property="HorizontalAlignment" Value="Center" />
     <Setter Property="VerticalAlignment" Value="Center" />
</Style>

<Style x:Key="MetroFlowItemMainBody" TargetType="Panel">
     <Setter Property="Background" Value="Orange" />
     <Setter Property="Margin" Value="6, 0" />
</Style>

<Style TargetType="c4f:MetroFlowItem">
     <Setter Property="Template">
          <Setter.Value>
               <ControlTemplate TargetType="c4f:MetroFlowItem">
                    <Grid>
                         <Grid Style="{StaticResource MetroFlowItemMainBody}">
                              <Image
                              Source="{TemplateBinding ImageSource}"
                              Visibility="{TemplateBinding ImageVisibility}"
                              Opacity="{TemplateBinding ImageOpacity}"
                              Style="{StaticResource MetroFlowItemImage}" />
                              <Grid VerticalAlignment="Bottom">
                                   <Rectangle
                                   Style="{StaticResource MetroFlowItemRectangleUnderlay}" />
                                   <TextBlock
                                   Text="{TemplateBinding Title}"
                                   Visibility="{TemplateBinding TitleVisibility}"
                                   Opacity="{TemplateBinding TitleOpacity}"
                                   Style="{StaticResource MetroFlowItemTextBlockStyle}"
                                   Foreground="Green"/>
                                   <TextBlock
                                   Text="{TemplateBinding ItemIndexString}"
                                   Visibility="{TemplateBinding ItemIndexVisibility}"
                                   Opacity="{TemplateBinding ItemIndexOpacity}"
                                   Style="{StaticResource MetroFlowItemTextBlockStyle}"
                                   Foreground="Blue"/>
                              </Grid>
                         </Grid>
                         <Rectangle Fill="Transparent" />
                    </Grid>
               </ControlTemplate>
          </Setter.Value>
     </Setter>
</Style>

Como podemos observar en la captura superior, hemos establecido el color de fondo a naranja, el color de fondo del Title en amarillo y  el color del Title en azul exceptuando el color del Title correspondiente al elemento seleccionado que es de color verde. De manera muy sencilla podemos personalizar a nuestro gusto la visualización del control.

Puedes ver en video el resultado de nuestro ejemplo a continuación:

También puedes descargar el ejemplo realizado:

Nada más en esta entrada. Hemos visto un control bastante interesante (yo lo utilizo en una de mis aplicaciones). Os recomiendo que lo probéis. Si os surgen dudas o sugerencias podéis dejarlas en los comentarios.

Más Información:

WindowsPhoneGeek: Getting Started with the Coding4Fun toolkit MetroFlow Control.

DZone: Addition to the Coding4Fun Toolkit – MetroFlow.

Windows Phone. Introducción al Coding4Fun Toolkit.

El SDK de Windows Phone es bastante versátil y nos proporciona una fuente bastante extensa de controles como para realizar una interfaz de usuario rica y atractiva. Sin embargo, en determinadas ocasiones podemos echar de menos más controles. Ya hemos hablado del Windows Phone Silverlight Toolkit en esta entrada. Pero si aún echamos de menos controles, resultará muy interesante el Coding4Fun Toolkit para Windows Phone.

Es un paquete de controles totalmente gratuito disponible en Codeplex. Podremos descargar tanto los archivos binarios como el código fuente. Además también hay documentación y un proyecto de ejemplo (Test Application).

¿Cuántos controles nos ofrece?

A continuación podemos ver el listado:

  • AboutPrompt. Mensaje emergente con propiedades especialmente pensadas para mostrar la típica ventana “Acerca de” de la aplicación. Podemos indicar la versión, autor, métodos de contacto, etc.

  • InputPrompt. Mensaje emergente donde se espera que el usuario porporcione información.

  • MessagePrompt. Mensaje emergente cuya finalidad es la de mostrar información al usuario.

  • PasswordInputPrompt. Similiar al InputPrompt pero se espera que el usuario proporcione una contraseña.

  • ColorPicker. Permite de manera fácil y elegante seleccionar un color.

  • Toast Prompt. Notificaciones. Útiles para notificar al usuario cuando han finalizado procesos en segundo plano.

  • ProgressOverlay. Superpone un ProgressBar sobre la interfaz. Muy útil para indicar actualizaciones de la interfaz de usuario.

  • RoundToggleButton. Deriva de ToggleButton por lo tanto tiene múltiples estados. Permite indicar una imágen de manera automática (ImageSource).

  • RoundButton. Deriva de Button. Permite indicar una imágen de manera automática (ImageSource).

  • TimeSpanPicker. Nos permite seleccionar fechas u horas de manera muy fácil e intuitiva.

  • MetroFlow. Interesante control. Nos permite crear pequeñas galerías de imágenes. Solo una de las imágenes está expandida.

  • Memory Counter. Muy útil a nivel de desarrollo. Nos permite de una manera muy sencilla controlar el consumo de memoria de nuestra aplicación. Recuerda que para poder publicar la aplicación en el MarketPlace la aplicación no puede exceder de cierto consumo de memoria.

Además de los controles vistos anteriormente, el Coding4Fun Toolkit nos ofrece:

Converters:

  • Boolean to Visibility
  • String To Visibility
  • Themed Image Converter
  • Inversed Theme Image Converter
  • Visibility to Boolean

Data Helpers:

  • PhoneHelper para obtener información del archivo de manifiesto.

Podéis ver a continuación un video de la aplicación de ejemplo que hace uso de todos los controles disponible en el código fuente:

Bien, interesante, pero… ¿Cómo se instala?

Como mencionamos anteriormente podemos encontrar el Coding4Fun Toolkit en Codeplex. La dirección sería:

http://coding4fun.codeplex.com

El primero de los enlaces es un archivo de instalación (.msi) que nos instalará los binarios.

EL segundo de los enlaces en un archivo comprimido (.zip) que contiene el código fuente. Aunque no pienses modificar los controles, te recomiendo si tienes tiempo echarle un vistazo.

Una vez descargado, ¿cómo usamos los controles del toolkit?

Es algo muy sencillo. Vamos a crear un proyecto para ver las dos formas posibles.

En la primera de las opciones debemos al proyecto las referencias a las librerías del Coding4Fun Toolkit:

La librería añadida se llamada “Coding4Fun.Phone.Controls.dll “.

Tras añadir la librería, para utilizar cualquiera de los controles desde un xaml debemos agregar el xmlns:

xmlns:c4f="clr-namespace:Coding4Fun.Phone.Controls;assembly=Coding4Fun.Phone.Controls"

Por ejemplo, para utilizar el control ColorSlider:

<c4f:ColorSlider />

La segunda de las opciones sería agregar todos los controles en una nueva sección de la caja de herramientas del Visual Studio.

Para ello haríamos clic derecho sobre la caja de herramientas y pulsaríamos sobre la opción “Add Tab”. Le pondríamos un nombre que nos ayude posteriormente a identificar el contenido de la sección como por ejemplo “Coding4Fun Toolkit”.

Por último, para agregar el contenido de la nueva sección haremos de nuevo clic derecho para seleccionar la opción “Choose Items”.

Se nos abrirá una ventana como la siguiente:

Buscaremos el ensamblado llamado “Coding4Fun.Phone.Controls” y lo seleccionaremos.

Listo!

Por facilitar el acceso he añadido un enlace directo a la descarga tanto de las librerías como del ejemplo mostrado en el video que acompaña a la entrada (correspondiente a la versión de 1.5.6):

Sin embargo, recomiendo encarecidamente realizar las descargas de la página de Codeplex donde conseguirás siempre las últimas versiones disponibles.

Más Información:

Codeproject. Having Fun with Coding4Fun’s Windows Phone 7 Controls. En inglés. Muy Recomendable.