Movilízate con Windows Phone 7 & Silverlight

El próximo día 10 de Noviembre a las 19:00 realizaré un WebCast sobre el desarrollo de aplicaciones de Windows Phone 7 basadas en Silverlight. Dicho WebCast constará de la siguiente agenda:

Windows Phone 7

-Arquitectura WP7
-Herramientas para desarrollar WP7 a través de Silverlight
-Animaciones en WP7(ejemplo)
-WP7 & API de Twitter(ejemplo)
-Media y almacenamiento aislado(ejemplo)
-implementación de una aplicación en un terminal con WP7

Si deseas inscribirte accede pincha aqui o sobre el banner.

Para saber más de Raul Mayo: http://geeks.ms/blogs/rmayo/
Organiza el UOC DotNetClub: http://uoc.dotnetclubs.com

Error en Windows Phone 7 “Zune software is not launched. Retry after making sure that Zune software is launched”

He estado instalando la nueva instalación de las Tools de Windows Phone 7, he creado una nueva solución y cual ha sido mi sorpresa, que al implementar la solución para que se ejecute en el emulador Visual Studio me muestra el siguiente error Zune software is not launched. Retry after making sure that Zune software is launched. En ese momento te preguntas para que necesitas Zune, pero todo tiene su explicación. Necesitas Zune si la solución la vas a implementar en el dispositivo, ya que es un requisito para su posterior sincronización. Para el caso que a mi me ocupa, simplemente nos vamos a Visual Studio y al lado del botón del simbolo Play que nos permite implementar la solución, simplemente debemos elegir la opción de implementar en el Windows Phone 7 Emulator en vez Windows Phone 7 Device que por defecto toma esta opción, como podemos ver a continuación:

image

Obtener datos de un servicio implementado en Windows Azure y presentarlos en Windows Phone 7 a través de un DataGrid

Como viene siendo habitual en gran parte de mis artículos, la tendencia es aprovechar las capacidades de nos ofrecen las distintas plataformas Microsoft, con el fin de obtener el mayor rendimiento de las aplicaciones que desarrollamos.En este caso vamos a crear un servicio WCF que alojaremos en Windows Azure. Seguidamente crearemos una aplicación de Windows Phone 7 basada en Silverlight que realizará la petición de una serie de datos, en función de un parámetro elegido por el usuario en la interfaz de usuario del terminal.

Vamos a comenzar con la creación de un nuevo servicio Windows Azure, responsable del envió de datos desde la nube a nuestro terminal en función de la opción que ha elegido el usuario final.

Para ello ejecutamos Visual Studio 2010 como administrador. Es importante que se ejecute con este Rol, de lo contrario no tendremos accesibilidad al servicio que nos proporcionará Windows Azure.

Una vez abierto Visual Studio 2010, elegimos Archivo->Nuevo Proyecto. Debemos elegir la plantilla Windows Azure Cloud Service(puedes descargar las herramientas para visual Studio 2010 aqui), que se encuentra dentro de las plantillas Cloud. En dicha aplicación le otorgaremos el nombre de ServicioAzureDepartamentos, la ubicación será la que deseemos mientras se encuentre en nuestro entorno local, como podemos ver a continuación:

image

Al crear dicho elemento en Visual Studio 2010, nos encontraremos con la siguiente ventana emergente:

image

 

Debemos añadir el rol ASP.NET Web Role a la solución de Windows Azure.

 

image

Presionamos OK para poder añadir el elemento nombrado con anterioridad. Al realizar esta acción se crearán dos proyectos (ServicioAzureDepartamentos y WebRole1). El primero es el que cargaremos en Windows Azure. El segundo, es el que desarrollamos el entorno local, que nos permite trabajar con el proyecto y ver los distintos comportamientos que tendría en la nube, pero desde nuestro entorno local.

El siguiente paso es la creación de un servicio WCF, en el que se le pasará un parámetro desde la aplicación Windows Phone 7. Se evaluará el parámetro con el fin de enviar los datos correspondientes a la solicitud. Estos son introducidos en una colección de elementos, basados en una clase que a su vez establece los campos que van a tener cada uno de los elementos dentro de la colección. Por último se devuelve la colección deseada para su posterior uso dentro de la interfaz de usuario del terminal.

Comenzamos haciendo clic con el botón derecho sobre WebRole1, elegimos Añadir->Nuevo elemento.

image

 

Debemos elegir la plantilla WCF Service, situada dentro de las plantilla Web, como podemos ver a continuación:

 

image

Seguidamente nos situamos en IService1.cs, donde vamos a modificar el ServiceContract que por defecto es incluido en Visual Studio 2010. La operación que realizamos es la llamada a un método del servicio pasándole el parámetro para que nos devuelva la colección de datos solicitada:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.Text;
  7. using System.Collections.ObjectModel;
  8.  
  9. namespace WebRole1
  10. {
  11.     // NOTE: You can use the «Rename» command on the «Refactor» menu to change the interface name «IService1» in both code and config file together.
  12.     [ServiceContract]
  13.     public interface IService1
  14.     {
  15.         [OperationContract]
  16.         ObservableCollection<empleado> ObtenerEmpleados(string departamento);
  17.     }
  18. }

 

Ahora nos situamos en Service1.svc.cs, donde definiremos la clase empleado( necesaria para asignar los campos que compondrán cada elemento de la colección) y el método que añade los diferentes datos que serán enviados al terminal.

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.Text;
  7. using System.Collections.ObjectModel;
  8.  
  9. namespace WebRole1
  10. {
  11.     // NOTE: You can use the «Rename» command on the «Refactor» menu to change the class name «Service1» in code, svc and config file together.
  12.     public class Service1 : IService1
  13.     {
  14.         ObservableCollection<empleado> ListaEmpleado = new ObservableCollection<empleado>();//lista basada en la clase empleado
  15.         public ObservableCollection<empleado> ObtenerEmpleados(string departamento)
  16.         {
  17.             //método que añade elementos a la colección en función del parámetro que a seleccionado en usuario
  18.             ListaEmpleado.Clear();//Limpiar la colección de elementos, siempre que esta necesite añadir nuevos
  19.             if (departamento == «Contabilidad»)
  20.             {
  21.                 ListaEmpleado.Add(new empleado() { Nombre = «María», Apellido = «Lopez», Email = «María@cein.es» });
  22.                 ListaEmpleado.Add(new empleado() { Nombre = «Juan», Apellido = «Martinez», Email = «JuanM@cein.es» });
  23.                 ListaEmpleado.Add(new empleado() { Nombre = «Beatriz», Apellido = «Suarez», Email = «BeatrizS@cein.es» });
  24.                 ListaEmpleado.Add(new empleado() { Nombre = «Blanca», Apellido = «Ramirz», Email = «BlancaRS@cein.es» });
  25.                 ListaEmpleado.Add(new empleado() { Nombre = «Miguel», Apellido = «Alvarez», Email = «MiguelA@cein.es» });
  26.             }
  27.             else if (departamento == «Informática»)
  28.             {
  29.                 ListaEmpleado.Add(new empleado() { Nombre = «Raúl», Apellido = «Mayo», Email = «RaulM@cein.es» });
  30.                 ListaEmpleado.Add(new empleado() { Nombre = «Sonía», Apellido = «Rodriguez», Email = «SoniaR@cein.es» });
  31.                 ListaEmpleado.Add(new empleado() { Nombre = «Pedro», Apellido = «Jimenez», Email = «PedroJ@cein.es» });
  32.                 ListaEmpleado.Add(new empleado() { Nombre = «Luis», Apellido = «Juarez», Email = «LuisJ@cein.es» });
  33.                 ListaEmpleado.Add(new empleado() { Nombre = «Ana», Apellido = «González», Email = «AnaG@cein.es» });
  34.                 ListaEmpleado.Add(new empleado() { Nombre = «Carlos», Apellido = «Acero», Email = «CarlosA@cein.es» });
  35.  
  36.             }
  37.             else if (departamento == «Dirección»)
  38.             {
  39.                 ListaEmpleado.Add(new empleado() { Nombre = «Blanca», Apellido = «Gomez», Email = «BlancaG@cein.es» });
  40.                 ListaEmpleado.Add(new empleado() { Nombre = «Patricia», Apellido = «Perez», Email = «PatriciaP@cein.es» });
  41.                 ListaEmpleado.Add(new empleado() { Nombre = «Fernando», Apellido = «Arbizu», Email = «FernandoA@cein.es» });
  42.                 ListaEmpleado.Add(new empleado() { Nombre = «NoAzure», Apellido = «Microsoft», Email = «NoAzure@cein.es» });
  43.  
  44.             }
  45.             else
  46.             {
  47.                 ListaEmpleado.Add(new empleado() { Nombre = «Julio», Apellido = «Ramirez», Email = «JulioR@cein.es» });
  48.                 ListaEmpleado.Add(new empleado() { Nombre = «Estela», Apellido = «Matín», Email = «EstelaM@cein.es» });
  49.                 ListaEmpleado.Add(new empleado() { Nombre = «Antonio», Apellido = «Blanco», Email = «AntonioB@cein.es» });
  50.                 ListaEmpleado.Add(new empleado() { Nombre = «Arturo», Apellido = «Miguelez», Email = «ArturoM@cein.es» });
  51.             }
  52.             return ListaEmpleado;
  53.         }
  54.     }
  55.  
  56.     public class empleado
  57.     {
  58.         //clase que define los campos de cada elemento de la lista
  59.         public string Nombre { get; set; }
  60.         public string Apellido { get; set; }
  61.         public string Email { get; set; }
  62.  
  63.     }
  64. }

Seguidamente nos situamos en WebRole1, con el botón derecho sobre el mismo debemos elegir la opción de que la aplicación inicie desde el citado elemento. Como podemos ver a continuación:

image

De este modo ejecutamos la aplicación F5 y se iniciará la simulación de nuestro servicio en nuestro entorno local de Windows Azure, de forma que nos aparecerá una pantalla similar a la siguiente:

image

 

El siguiente paso que vamos a dar es la elaboración de la interfaz de usuario de Windows Phone 7. Esta contará con una imagen corporativa, una serie de departamentos que el usuario podrá elegir y un DataGrid sobre el que se presentarán los diferentes datos de los empleados pertenecientes al departamento seleccionado.

Comenzamos creando un nuevo proyecto en Visual Studio 2010, elegimos la plantilla Aplicación Windows Phone, esta se encuentra dentro de las plantillas de Silverlight para Windows Phone.

Establecemos el nombre de la aplicación como Personal y la ubicación del mismo será en el mismo entorno que el proyecto Windows Azure creado anteriormente como podemos observar a continuación:

image

Para poder utilizar el objeto DataGrid en Windows Phone 7 tenemos que añadir la librería PhoneDataGrid.dll (dicha librería la podéis encontrar aquí). Una vez descargada la librería la vamos añadirla mediante el clic del botón derecho  del ratón sobre la carpeta Reference y elegimos Añadir Referencia. En la ventana emergente seleccionamos la pestaña Buscar, nos desplazamos hasta la ubicación donde ha sido descargada la librería PhoneDataGrid.dll.

Ahora vamos a construir la interfaz de usuario que contará con una imagen corporativa, un bloque de texto, un ListBox que mostrará los diferentes departamentos de la organización y por ultimo un DataGrid que presentará los respectivos datos. Nos situamos en MainPage.xaml e introducimos el código correspondiente con la citada interfaz de usuario:

  1. <phone:PhoneApplicationPage
  2.     x:Class=»Personal.MainPage»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:phone=»clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone»
  6.     xmlns:shell=»clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone»
  7.     xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
  8.     xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
  9.     xmlns:datagridphone=»clr-namespace:PhoneDataGridControl;assembly=PhoneDataGrid»
  10.     mc:Ignorable=»d» d:DesignWidth=»480″ d:DesignHeight=»768″
  11.     FontFamily=»{StaticResource PhoneFontFamilyNormal}«
  12.     FontSize=»{StaticResource PhoneFontSizeNormal}«
  13.     Foreground=»{StaticResource PhoneForegroundBrush}«
  14.     SupportedOrientations=»Portrait» Orientation=»Portrait»
  15.     shell:SystemTray.IsVisible=»True»>
  16.  
  17.     <!–LayoutRoot is the root grid where all page content is placed–>
  18.     <Grid x:Name=»LayoutRoot» Background=»Transparent»>
  19.         <Grid.RowDefinitions>
  20.             <RowDefinition Height=»Auto»/>
  21.             <RowDefinition Height=»*»/>
  22.         </Grid.RowDefinitions>
  23.  
  24.         <!–TitlePanel contains the name of the application and page title–>
  25.         <StackPanel x:Name=»TitlePanel» Grid.Row=»0″ Margin=»12,17,0,28″>
  26.             <Image Source=»CEIN.png»/>
  27.         </StackPanel>
  28.  
  29.         <!–ContentPanel – place additional content here–>
  30.         <Grid x:Name=»ContentPanel» Grid.Row=»1″ Margin=»12,0,12,0″>
  31.             <datagridphone:DataGrid AutoGenerateColumns=»True»
  32.                 Background=»Black» AlternatingRowBackground=»Blue»
  33.                 RowBackground=»Blue» GridLinesVisibility=»All»
  34.                 VerticalScrollBarVisibility=»Visible» Margin=»0,209,6,6″                    
  35.                 HeadersVisibility=»All» Name=»dgPhone»>
  36.             </datagridphone:DataGrid>
  37.             <ListBox Height=»115″ HorizontalAlignment=»Left» Margin=»35,88,0,0″ Name=»Departamentos» VerticalAlignment=»Top» Width=»390″ SelectionChanged=»Departamentos_SelectionChanged»>
  38.                 <ListBoxItem Content=»Contabilidad»/>
  39.                 <ListBoxItem Content=»Informática»/>
  40.                 <ListBoxItem Content=»Dirección»/>
  41.                 <ListBoxItem Content=»Logística»/>
  42.             </ListBox>
  43.             <TextBlock Height=»85″ HorizontalAlignment=»Left» Margin=»12,6,0,0″ Name=»titulo» Text=»ELEGIR EL DEPARTAMETO SOBRE EL QUE DESEA OBTENER LOS DIFERENTES EMPLEADOS:» VerticalAlignment=»Top» Width=»433″ TextWrapping=»Wrap» />
  44.         </Grid>
  45.     </Grid>
  46.     <!–Sample code showing usage of ApplicationBar–>
  47.     <!–<phone:PhoneApplicationPage.ApplicationBar>
  48.         <shell:ApplicationBar IsVisible=»True» IsMenuEnabled=»True»>
  49.             <shell:ApplicationBarIconButton IconUri=»/Images/appbar_button1.png» Text=»Button 1″/>
  50.             <shell:ApplicationBarIconButton IconUri=»/Images/appbar_button2.png» Text=»Button 2″/>
  51.             <shell:ApplicationBar.MenuItems>
  52.                 <shell:ApplicationBarMenuItem Text=»MenuItem 1″/>
  53.                 <shell:ApplicationBarMenuItem Text=»MenuItem 2″/>
  54.             </shell:ApplicationBar.MenuItems>
  55.         </shell:ApplicationBar>
  56.     </phone:PhoneApplicationPage.ApplicationBar>–>
  57.  
  58. </phone:PhoneApplicationPage>

 

Este será el aspecto de nuestra interfaz de usuario:

image

A continuación  vamos añadir el servicio Windows Azure que trabaja en el entorno local, para poder trabajar con el mismo, pidiéndole la lista de datos que requiere el usuario final.

Empezamos haciendo clic sobre la carpeta Referencias del proyecto Personal creado con anterioridad. Debemos elegir Añadir->Service Reference.

En la ventana emergente en el campo Address vamos a introducir (en mi caso http://127.0.0.1:81/Service1.svc) la dirección del servicio que hemos añadido con anterioridad.

Presionamos sobre el botón GO, para comprobar que tenemos acceso al servicio. En el apartado NameSpace dejamos el nombre que por defecto nos ofrece Visual Studio 2010. El resultado de estas acciones lo podemos ver en la siguiente imagen:

image

Presionamos Ok, para añadir el servicio a nuestra aplicación WP7.

image

 

En el siguiente paso vamos a obtener los datos de los empleados del departamento que seleccione el usuario en la interfaz de usuario del terminal. Se pasará el parámetro y este será devuelto a través del servicio creado en el entorno local de Windows Azure. Todo este proceso se realiza de forma asíncrona.

Para comenzar vamos a situarnos en el ListBox que contiene los diferentes departamentos (Departamentos). En este objeto vamos a añadirle el evento SelectionChanges, para ello seleccionamos con el objeto Departamentos seleccionado nos situamos en la pestaña Eventos del visor de propiedades de Visual Studio 2010. En la propiedad SelectionChanges realizamos doble clic sobre esta, lo que generará el código Behind de dicho evento.

image

Una vez situados en el código Behind, vamos a situarnos en el constructor para añadir una variable que tendrá el valor del ítem seleccionado en el control Departamentos.

  1. namespace Personal
  2. {
  3.     public partial class MainPage : PhoneApplicationPage
  4.     {
  5.         string DepartamentoSeleccionado;
  6.         // Constructor
  7.         public MainPage()
  8.         {
  9.             InitializeComponent();
  10.         }

 

Ahora dentro del evento que hemos creado con anterioridad primeramente vamos a obtener el contenido del ítem seleccionado.

  1. private void Departamentos_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2.         {
  3.             ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
  4.             DepartamentoSeleccionado = lbi.Content.ToString();//variable que obtiene el contenido del
  5.             //elemento seleccionado en la lista de departamentos
  6.             
  7.         }

El siguiente paso es referenciar nuestro servicio en el código Behind de la aplicación, así que tenemos que añadir la siguiente directiva:

using Personal.ServiceReference1;

Ahora vamos a realizar la llamada al servicio de forma asíncrona, cuando realizamos esta acción debemos de pasar el nombre del departamento seleccionado por el usuario. Por otro lado vamos a crear un controlado de eventos, para que cuando la llamada haya sido completada, los datos devueltos sean cargados en el DataGrid, todo esto lo podemos ver en el siguiente fragmento de código:

  1. private void Departamentos_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2.         {
  3.             ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
  4.             DepartamentoSeleccionado = lbi.Content.ToString();//variable que obtiene el contenido del
  5.             //elemento seleccionado en la lista de departamentos
  6.             Service1Client proxy = new Service1Client();
  7.             proxy.ObtenerEmpleadosCompleted += new EventHandler<ObtenerEmpleadosCompletedEventArgs>(proxy_ObtenerEmpleadosCompleted);
  8.             //controlador del evento en el que se a completado la llamado al método del servivio Windows Azure
  9.             proxy.ObtenerEmpleadosAsync(DepartamentoSeleccionado);
  10.             //llamada asincrona al método de Windows Azure
  11.         }
  12.         void proxy_ObtenerEmpleadosCompleted(object sender, ObtenerEmpleadosCompletedEventArgs e)
  13.         {
  14.             dgPhone.ItemsSource = e.Result.ToList<ServiceReference1.empleado>();
  15.             //Rellenar el DataGrid con la lista obtenido desde el servicio Windows Azure
  16.         }

Si ejecutamos la aplicación vemos que se obtienen los datos del servicio pero desde un entramado local, si deseamos tenerlo en la nube deberemos tener las siguientes características:

  • Tener una cuenta Azure

image

 

  • Tener creado espacio de alojamiento de proyectos en Windows Azure y un almacén de datos dentro de la citada plataforma.

image

Teniendo estas características, es el momento de publicar el servicio en la nube. Accedemos al proyecto ServicioAzureDepartamentos, presionamos con el botón derecho sobre ServicioAzureDepartamentos y elegimos publicar como podemos ver a continuación:

image

 

 

Al realizar esta acción nos aparecerá una ventana donde debemos introducir los diferentes credenciales de acceso a nuestra plataforma Windows Azure.

 

image

Una vez que tengamos introducidos los credenciales, nuestro servicio estará alojado en nuestra plataforma Windows Azure, bien en el entorno de producción o bien en el entorno de preproducción.

 

image

Cada uno de estos entornos tiene una dirección URL a la que podemos acceder para poder trabajar con ella. En nuestro caso trabajaremos con http://direcciónproducciónAzure/Service1.svc para poder acceder al servicio que hemos alojado con anterioridad.

Por último vamos redireccionar la petición de datos desde nuestra aplicación de Windows Phone 7 al servicio implementado en Windows Azure.

Por último nos situamos en la aplicación Windows Phone 7 (Personal), accedemos a ServiceReferences.ClientConfig y cambiamos la dirección del servicio local por la dirección del servicio en Windows Azure como podemos observar a continuación:

  1. <configuration>
  2.     <system.serviceModel>
  3.         <bindings>
  4.             <basicHttpBinding>
  5.                 <binding name=«BasicHttpBinding_IService1« maxBufferSize=«2147483647«
  6.                     maxReceivedMessageSize=«2147483647«>
  7.                     <security mode=«None« />
  8.                 </binding>
  9.             </basicHttpBinding>
  10.         </bindings>
  11.         <client>
  12.             <endpoint address=«http://127.0.0.1:81/Service1.svc« binding=«basicHttpBinding«
  13.                 bindingConfiguration=«BasicHttpBinding_IService1« contract=«ServiceReference1.IService1«
  14.                 name=«BasicHttpBinding_IService1« />
  15.         </client>
  16.     </system.serviceModel>
  17. </configuration>

 

Ahora ejecutamos la aplicación WP7 y comprobamos que la petición de los empleados del departamento se realiza sobre la plataforma Windows Azure. Cambiando los datos tanto en Azure como en el servicio Azure en el entorno local podemos ver la diferencia de uno respecto del otro.

Como podéis comprobar la unión de las plataformas nos ayuda en el desarrollo de aplicaciones de negocio, así como en la calidad que ofrecemos a nuestro clientes.

Agradecer la posibilidad de realizar este artículo gracias a las  nociones y la librería que usa Walter Ferrari.

Si deseas saber más sobre aplicaciones de negocio en Silverlight mira esto.