Silverlight ILUMINA TU CÓDIGO

ILUMINA TU CÓDIGO

LA REVOLUCIÓN SILENCIOSA
Interactuar con Windows MarketPlace desde Windows Phone 7

Microsoft al crear el nuevo sistema operativo para movilidad, generó a su vez el portal MarketPlace, donde puede encontrar todo lo necesario para el citado sistema operativo. En un terminal en el que este instalado WP7 accedes a MarketPlace a través de los Hub o el navegador. Pero mi inquietud surgió cuando queria interactuar de forma personalizada con el portal. Para ello voy a exponeros como podéis interactuar desde un terminal con WP7 en MarketPlace.

Comenzaremos creando desde Visual Studio 2010 un nuevo proyecto.

image 

Elegimos Windows Phone Application dentro de las plantillas Silverlight for Windows Phone, como podemos observar en la anterior imagen. Nombraremos dicho proyecto como MarketPlace para su fácil reconocimiento.

En el proyecto que hemos creado voy a crear una carpeta en la que incluiré los iconos con los que el usuario final va a interactuar desde el terminal. Los iconos que utilizaremos son los de aplicaciones, música, búsqueda y comentarios de usuarios. Podéis descargaros el paquete de iconos aquí

image

Debemos de cambiar en cada uno de los iconos la propiedad Build Action al valor Content y la propiedad Copy to Output Directory al valor Copy if newer.

image

Seguidamente vamos a acceder al diseño de nuestra aplicación (MainPage.xaml) para introducir los distintos iconos en el menú destinado para tal fin. Como puedes observar por defecto la Barra de iconos aparece comentada. Simplemente debemos des comentarla y añadir el siguiente fragmento de código:

  1. <phone:PhoneApplicationPage.ApplicationBar>
  2.         <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
  3.             <shell:ApplicationBarIconButton x:Name="MarketButton"
  4.            IconUri="/AppBarIcons/appbar.folder.rest.png"
  5.            Text="market" />
  6.             <shell:ApplicationBarIconButton x:Name="MusicButton"
  7.            IconUri="/AppBarIcons/appbar.feature.video.rest.png"
  8.            Text="music" />
  9.             <shell:ApplicationBarIconButton x:Name="SearchButton"
  10.            IconUri="/AppBarIcons/appbar.feature.search.rest.png"
  11.            Text="search" />
  12.             <shell:ApplicationBarIconButton x:Name="ReviewButton"
  13.            IconUri="/AppBarIcons/appbar.share.rest.png"
  14.            Text="reviews" />
  15.  
  16.         </shell:ApplicationBar>
  17.     </phone:PhoneApplicationPage.ApplicationBar>

Seguidamente vamos añadir el controlador del evento clic para cada uno de los iconos.

image

Siendo el resultado final del código de los distintos iconos el siguiente:

  1. <phone:PhoneApplicationPage.ApplicationBar>
  2.         <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
  3.             <shell:ApplicationBarIconButton x:Name="MarketButton"
  4.            IconUri="/AppBarIcons/appbar.folder.rest.png"
  5.            Text="market" Click="MarketButton_Click"/>
  6.             <shell:ApplicationBarIconButton x:Name="MusicButton"
  7.            IconUri="/AppBarIcons/appbar.feature.video.rest.png"
  8.            Text="music" Click="MusicButton_Click"/>
  9.             <shell:ApplicationBarIconButton x:Name="SearchButton"
  10.            IconUri="/AppBarIcons/appbar.feature.search.rest.png"
  11.            Text="search" Click="SearchButton_Click"/>
  12.             <shell:ApplicationBarIconButton x:Name="ReviewButton"
  13.            IconUri="/AppBarIcons/appbar.share.rest.png"
  14.            Text="reviews" Click="ReviewButton_Click"/>
  15.  
  16.         </shell:ApplicationBar>
  17.     </phone:PhoneApplicationPage.ApplicationBar>

Presionamos con el botón derecho sobre el proyecto MainPage.xaml  y elegimos la opción View Code de este modo accedemos a el código Behind de nuestra aplicación.

Debemos referenciar las librería que permite realizar el acceso a MarketPlace, ya que es una de las tareas que tiene asignada por defecto WP7. Introducimos la referencia:

using Microsoft.Phone.Tasks;

Ahora vamos a introducir las diferentes acciones que van a realizar los iconos al ser presionados.Comenzamos por el icono de MarketPlace que nos presentará la página de inicio de dicho portal con las principales novedades.

  1. private void MarketButton_Click(object sender, EventArgs e)
  2.         {
  3.             MarketplaceHubTask marketPlace = new MarketplaceHubTask();
  4.             marketPlace.ContentType = MarketplaceContentType.Applications;
  5.             marketPlace.Show();
  6.  
  7.         }

Seguidamente aplicaremos el código correspondiente para el botón Música, que abrirá el Hub relacionado con toda la música existente en MarketPlace:

  1. private void MusicButton_Click(object sender, EventArgs e)
  2.         {
  3.             MarketplaceHubTask marketPlace = new MarketplaceHubTask();
  4.             marketPlace.ContentType = MarketplaceContentType.Music;
  5.             marketPlace.Show();
  6.  
  7.         }

Para el botón de búsqueda, el sistema operativo realizará una búsqueda en el portal de las aplicaciones relacionadas con las cadena introducida por el usuario final en el terminal:

  1. private void SearchButton_Click(object sender, EventArgs e)
  2.         {
  3.             MarketplaceSearchTask marketSearch = new MarketplaceSearchTask();
  4.             marketSearch.ContentType = MarketplaceContentType.Applications;
  5.             marketSearch.SearchTerms = "Photo";
  6.             marketSearch.Show();
  7.  
  8.         }

Finalmente el botón Review permitirá ver los comentarios de las aplicaciones utilizadas por los diferentes usuarios, para ello introducimos el siguiente código:

 

  1. private void ReviewButton_Click(object sender, EventArgs e)
  2.         {
  3.             MarketplaceReviewTask marketReview = new MarketplaceReviewTask();
  4.             marketReview.Show();
  5.  
  6.         }

Ahora solo nos queda probar la interactuación personalizada de nuestro terminal con MarketPlaces, para ello ejecutamos nuestro proyecto (F5):

image            image            image

Springboard Series Tour en CESNAVARRA

¿Conoces el Springboard Series Tour? Es el evento para los profesionales de Sistemas TIC, gerentes y directores de Sistemas de cualquier empresa y  cualquier persona en general interesada en la mejor administración de sus sistemas informáticos.

La gira de este año enseñará todo lo que hace falta conocer para desplegar Windows7 y Office 2010 sin problemas, como gestionar los diversos accesos a nuestros sistemas de empresa con seguridad y confianza y todo lo que necesitas saber para virtualizar aplicaciones.

Además, tenemos todo un elenco de ponentes de primera fila:

- Miguel Hernández

- Paulo Días

- Fernando Guillot

- David Nudelman

- Dani Alonso

 

image   image   image   image   image

Anímate y comparte con nosotros una jornada que ha sido un éxito en toda Europa y que por primera vez traemos a Pamplona.

Toda la información de la jornada está disponible en este enlace de nuestra página web

Tipos de estilos en WPF & Silverlight
  • Estilo Heredado:

Permite definir un estilo como recurso para personalizar cualquier control de la interfaz de usuario.

  • Definición:
  1. <Style x:Key="estilo1" >
  2.             <Setter Property="Control.FontFamily" Value="Arial"/>
  3.             <Setter Property="Control.FontSize" Value="22"/>
  4.             <Setter Property="Control.Background" Value="Red"/>
  5.         </Style>
  • Aplicación:
  1. <Button Content="Pincha Aquí!!" Height="54" HorizontalAlignment="Left"
  2.                 Margin="134,132,0,0" Name="button1" VerticalAlignment="Top" Width="105"
  3.                 Style="{StaticResource estilo1}" />

 

  • Estilo por tipo

Permite definir un estilo como recurso para personalizar cualquier el tipo de control que decidamos.

  • Definición:

  1. <Style x:Key="estilo2" TargetType="TextBlock">
  2.             <Setter Property="Control.FontFamily" Value="Broadway"/>
  3.             <Setter Property="Control.FontSize" Value="30"/>
  4.             <Setter Property="Control.Background" Value="Orange"/>
  5.         </Style>

  • Aplicación:
  1. <TextBlock Height="130" HorizontalAlignment="Left" Margin="156,0,0,0" Name="textBlock1" Text="Bienveidos a WPF"
  2.                    VerticalAlignment="Top" Width="308" Style="{StaticResource estilo2}" />
  • Estlo por Tigger

Permite definir un estilo como recurso y aplicarlo en función de un disparador de un evento(Trigger), hay dos tipo de esta clase:

  • Trigger por Evento:

Este tipo de evento permite el cambio de las propiedades de un objeto cuando ocurre un evento. Pero además permite la realización de acciones dentro del estilo como por ejemplo realizar una animación del objeto sobre el que se va aplicar el estilo.

  • Definición:
  1. <Style x:Key="evento" TargetType="Rectangle">
  2.             <Setter Property="Fill" Value="RoyalBlue"/>
  3.             <Style.Triggers>
  4.                 <EventTrigger RoutedEvent="MouseEnter">
  5.                     <EventTrigger.Actions>
  6.                         <BeginStoryboard>
  7.                             <Storyboard>
  8.                                 <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="Opacity" To="0">
  9.                                 </DoubleAnimation>
  10.                             </Storyboard>
  11.                         </BeginStoryboard>
  12.                     </EventTrigger.Actions>
  13.                 </EventTrigger>
  14.                 <EventTrigger RoutedEvent="MouseLeave">
  15.                     <EventTrigger.Actions>
  16.                         <BeginStoryboard>
  17.                             <Storyboard>
  18.                                 <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="Opacity" To="1">
  19.                                 </DoubleAnimation>
  20.                             </Storyboard>
  21.                         </BeginStoryboard>
  22.                     </EventTrigger.Actions>
  23.                 </EventTrigger>
  24.             </Style.Triggers>
  25.             
  26.         </Style>
  • Aplicación:
  1. <Rectangle Height="200" Width="200" Fill="Black" Style="{StaticResource evento}"></Rectangle>
  • Trigger por Datos:

Permite la transformación de las propiedades de un control, basándose en los datos introducidos en otro control diferente.

Definición:

  1. <Style x:Key="datos" TargetType="Rectangle">
  2.             <Setter Property="Fill" Value="BurlyWood"/>
  3.             <Style.Triggers>
  4.                 <DataTrigger Binding="{Binding ElementName=Entrada,Path=Text}" Value="Rojo">
  5.                     <Setter Property="Fill" Value="Red"></Setter>
  6.                 </DataTrigger>
  7.                 <DataTrigger Binding="{Binding ElementName=Entrada,Path=Text}" Value="Azul">
  8.                     <Setter Property="Fill" Value="Blue"></Setter>
  9.                 </DataTrigger>
  10.                 <DataTrigger Binding="{Binding ElementName=Entrada,Path=Text}" Value="Verde">
  11.                     <Setter Property="Fill" Value="Green"></Setter>
  12.                 </DataTrigger>
  13.                 <DataTrigger Binding="{Binding ElementName=Entrada,Path=Text}" Value="Amarillo">
  14.                     <Setter Property="Fill" Value="Yellow"></Setter>
  15.                 </DataTrigger>
  16.                 <DataTrigger Binding="{Binding ElementName=Entrada,Path=Text}" Value="Negro">
  17.                     <Setter Property="Fill" Value="Black"></Setter>
  18.                 </DataTrigger>
  19.             </Style.Triggers>
  20.         </Style>

Aplicación:

  1. <Grid>
  2.         <TextBox Height="23" HorizontalAlignment="Left" Margin="190,46,0,0" Name="Entrada" VerticalAlignment="Top" Width="120" />
  3.         <Label Content="Elige el color:" Height="24" Name="label" HorizontalAlignment="Left"
  4.                Margin="100,44,0,0" VerticalAlignment="Top" Width="94" />
  5.         <Rectangle Stroke="red" Margin="171,134,80,35" Style="{StaticResource datos}"></Rectangle>
  6.     </Grid>
Posted: 22/12/2010 13:36 por RAÚL MAYO | con no comments
Archivado en: ,
Trio de ases en Windows Phone 7

Si lo tuyo es el desarrollo en entornos de movilidad, no deberías perderte el evento del próximo 14 de diciembre que realizaremos en los Centros de Excelencia Software de Navarra, donde contaremos con: 

  • Eduardo Ortega, MVP en Movilidad perteneciente al Centro de Innovación en Movilidad de Microsoft

  • Isabel Gómez, Evangelista de Fabricantes de Software en Microsoft Ibérica

  • Iñaki Ayucar, MVP en DirectX/XNA y fundador de la empresa SIMAX

    EduOrtega     ponenteIsabelGomez     IAyucar

  •  

    Si deseas vivir una nueva experiencia a través de Windows Phone 7 y lanzarte a desarrollar en la citada plataforma deberías registrarte aquí para poder asistir.

    Posted: 9/12/2010 12:05 por RAÚL MAYO | con 2 comment(s)
    Archivado en:
    Utilizar Sample Data en Silverlight a través de Expression Blend

    Cuando comenzamos un nuevo proyecto , este consta de una parte de diseño y otra de desarrollo. En la mayoría de los desarrollos, el diseñador cuando  incluye elementos en la interfaz de usuario, no suele saber como estos son visualizados por el usuario final. Dicho objetivo lo consigue cuando el diseño es implementado con la parte elaborada por el desarrollador. Para este inconveniente, Microsoft nos plantea una solución a través de Expression Blend 4. Es la posibilidad de enlazar los distintos objetos de la interfaz de usuario con datos de ejemplo(Sample Data), que aunque el contenido de estos datos poco tengan que ver con el real, si que el formato de los mismos es exactamente el que va tener la aplicación final.

    Para entender esta nueva funcionalidad, vamos a empezar abriendo Expression Blend 4, bien creamos un nuevo proyecto de Silverlight o abrimos uno existente. En la parte superior derecha Expression Blend 4 nos ofrece tres pestañas (Propiedades,Recursos y Datos).

    1

    Seleccionamos la pestaña Datos, dentro de esta pestaña vamos a crear un nuevo Sample Data. Para ello presionamos en el icono que se muestra en la siguiente imagen:

    2

    Una vez presionado dicho icono elegimos la opción New Sample Data:

    3

    En la ventana emergente debemos otorgarle un nombre con el que sea fácilmente reconocible, en mi caso como mi aplicación va a basarse en los contactos de mi empresa, este será el nombre que le otorgaré como podemos ver a continuación:

    4

    Al realizar dicha acción por defecto dentro de nuestro Sample Data se ha generado una colección que consta a su vez de dos propiedades, veremos más adelante como podemos añadir, editar o eliminar estas colecciones y propiedades:

    5

    Seguidamente la colección la nombraremos como DPersonales, dentro de dicha colección vamos a introducir tres propiedades que llamaremos (Nombre, Apellidos y Dni). Por defecto se han creado dos propiedades, para añadir una nueva, debemos presionar sobre el icono más, junto a la colección DPersonales, como podemos observar en la siguiente imagen:

    6

    Por otro lado, cada una de las propiedades podemos otorgarle el forma que sea más adecuado a nuestras necesidades. Para ello desplegamos la propiedad Nombre y elegimos el formato que se muestra en la siguiente imagen:

    7

    Entrando más en materia como podemos observar no solo podemos elegir el tipo de datos que puede introducir el usuario, también podemos controlar el formato de los datos.

    A continuación vamos añadir una nueva propiedad, en este caso la nombraremos como foto. El tipo de datos ha de ser Image, por otro lado debemos elegir la ubicación donde se encuentran los citados elementos como podemos ver a continuación:

    8

    Por último, ¿cómo mostramos los datos en la interfaz de usuario?. Simplemente seleccionamos la colección DPersonales y la arrastramos al área de diseño de Expression Blend 4:

    9

    Al realizar la anterior acción, nos crea un ListBox en el que aparecen los elementos de la colección en cada uno de los items del ListBox:

    10

    El ListBox por defecto podemos personalizarlo como nosotros deseemos a través de las plantillas. Para ello vamos añadir una propiedad , pero esta ha de ser compleja debido a que dentro de esta propiedad compleja añadiremos propiedades simples.

    11

    Nombramos la propiedad compleja como Edad y dentro añadimos dos propiedades simples llamadas Años y Fecha Nacimiento. El campo Años será de tipo Número y una longitud de 3 dígitos. El campo Fecha de Nacimiento será de tipo cadena pero de formato de fecha.

    12 

    Seguidamente vamos añadir al ListBox un nuevo campo (Años). Para ello seleccionamos el citado elemento, presionamos con el botón derecho sobre el y seleccionamos Edit Additional Templates->Edit Generated Items->Edit Current. De este modo vamos a poder editar la plantilla que representa la apariencia de cada uno de los items del ListBox.

    13

    Dentro de la plantilla vamos a introducir un nuevo objeto. Accedemos a la barra de herramientas seleccionamos el objetos Textblock y lo introducimos dentro de la plantilla. El siguiente paso es enlazar dicho objeto con los datos de ejemplos de la edad (Años) como podemos observar a continuación:

    14

    Cerramos la plantilla presionado sobre le icono 16 y ejecutamos la aplicación siendo el aspecto de la misma el siguiente:

    17

    Gracias a Sample Data podemos asimilar la presentación de los datos antes de implementar nuestro diseño con la parte de desarrollo de cualquier proyecto, consiguiendo con ello la eliminación de posibles errores y el cumplimiento de tiempos.

    Posted: 7/12/2010 13:28 por RAÚL MAYO | con no comments
    Archivado en:
    Vive una nueva dimensión de la movilidad con Windows Phone 7

    El próximo 14 de diciembre de 11h a 14h en los CES , podréis vivir una nueva experiencia en lo que a movilidad se refiere. Para ello contamos con el MVP en movilidad Eduardo Ortega, perteneciente al Centro de Innovación en Movilidad de Microsoft, Isabel Gómez, Evangelista de Fabricantes de Software en Microsoft Ibérica e Iñaki Ayucar, MVP en DirectX/XNA fundador de la empresa SIMAX

    Con Windows Phone 7 Microsoft ha dado una nueva dimensión a su plataforma de movilidad, centrándose además del área empresarial, en el área personal. Introduciendo “Experiencias” como XBOX LIVE, redes sociales, entornos dinámicos, etc...

    En el citado evento se mostrará cómo desarrollar entornos productivos, dinámicos y de alto rendimiento para conseguir interfaces de usuario enriquecidas mediante el uso de aplicaciones basadas en Silverlight.

    Por otro lado, podréis ver la elaboración de juegos en 3D basados en la plataforma XNA, donde se aprovecha todo el potencial Hardware que ofrecen los terminales Windows Phone 7, y el cual nos permite disfrutar de las experiencias XBOX LIVE con un nivel superior de rendimiento.

    Para obtener más información sobre el evento acceder aqui.

    WP7

    Posted: 25/11/2010 17:12 por RAÚL MAYO | con no comments
    Archivado en:
    Obtener las propiedades de configuración en un terminal Windows Phone 7

    Muchas aplicaciones necesitan saber que versión es el terminal, Firmware, fabricante o la cantidad de memoria en uso. ¿cómo podemos obtener estas propiedades??

    Simplemente tenemos que usar la clase DeviceExtendedProperties, de la que podemos obtener propiedades como:

    • Fabricante del Terminal
    • Nombre del Terminal
    • Versión de Firmware del Terminal
    • Versión Hardware del Terminal
    • Memoria Total del Terminal
    • Uso actual de la memoria de la aplicación
    • Uso de la memoria de pico de la aplicación

    Simplemente tenemos que añadir al código Behind de una aplicación de Windows Phone 7 el Siguiente fragmento de código:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Net;
    5. using System.Windows;
    6. using System.Windows.Controls;
    7. using System.Windows.Documents;
    8. using System.Windows.Input;
    9. using System.Windows.Media;
    10. using System.Windows.Media.Animation;
    11. using System.Windows.Shapes;
    12. using Microsoft.Phone.Controls;
    13. using Microsoft.Phone.Info;
    14.  
    15. namespace Configuración
    16. {
    17.     
    18.     public partial class MainPage : PhoneApplicationPage
    19.     {
    20.         string statsString;
    21.         // Constructor
    22.         public MainPage()
    23.         {
    24.             InitializeComponent();
    25.             var deviceManufacturer = DeviceExtendedProperties.GetValue("DeviceManufacturer");
    26.             var deviceName = DeviceExtendedProperties.GetValue("DeviceName");
    27.             //var deviceUniqueId = DeviceExtendedProperties.GetValue("DeviceUniqueId");
    28.             var deviceFirmwareVersion = DeviceExtendedProperties.GetValue("DeviceFirmwareVersion");
    29.             var deviceHardwareVersion = DeviceExtendedProperties.GetValue("DeviceHardwareVersion");
    30.             var deviceTotalMemory = DeviceExtendedProperties.GetValue("DeviceTotalMemory");
    31.             var applicationCurrentMemoryUsage = DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
    32.             var applicationPeakMemoryUsage = DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
    33.  
    34.             statsString = "Fabricante del Terminal: " + deviceManufacturer + "\n" +
    35.                 "Nombre del Terminal: " + deviceName + "\n" +
    36.                 "Versión de firmware del Terminal: " + deviceFirmwareVersion + "\n" +
    37.                 "Versión Hardware del Terminal: " + deviceHardwareVersion + "\n" +
    38.                 "Memoria Total del Terminal: " + deviceTotalMemory + "\n" +
    39.                 "Uso actual de la memoria de la aplicación: " + applicationCurrentMemoryUsage + "\n" +
    40.                 "Uso pico memoria de la app.: " + applicationPeakMemoryUsage;
    41.  
    42.             stats.Text = statsString;//texblock donde se presentan las configuraciones del terminal
    43.             
    44.         }
    45.         
    46.     }
    47.     
    48.  
    49. }

    El resultado en la interfaz del usuario sería el siguiente:

    WP7

    Posted: 24/11/2010 13:13 por RAÚL MAYO | con 1 comment(s)
    Archivado en:
    Sincronización contactos y calendario Outlook con Windows Phone 7

    Windows Phone 7 sincroniza tanto tus contactos como tu calendario a través de una cuenta compatible con Exchange ActiveSync (Protocolo de sincronización utilizado por Microsoft).

    El problema que se me ha planteado es sincronizar contactos y calendario de Outlook con Windows Phone 7. El gestor de correo no es compatible con los requerimientos mencionados con anterioridad.

    La solución, exportar tus contactos y citas del calendario a Hotmail a través de una cuenta Windows Live ID.

    Los pasos a seguir serán los siguientes:

    Exportar desde Outlook

    • En cuanto a contactos se refiere, comenzamos accediendo a Outlook 2003,07 o 10, para realizar la exportación de los contactos en un archivo de extensión .csv (contactos separados por comas, el más común).
    • Accedemos al menú Archivo->Importar y Exportar(2003-2007).
    • Seguidamente hacemos clic en exportar a un archivo y, a continuación, haga clic en siguiente.
    • Luego presionamos sobre Valores separados por comas (Windows) y, a continuación, hacemos clic en siguiente.
    • En la lista de carpetas, haga clic en la carpeta de contactos y, a continuación, haga clic en siguiente.
    • Desplácese hasta la carpeta donde desea guardar los contactos como un archivo. CSV.
    • Escriba un nombre para el archivo exportado y, a continuación, haga clic en Aceptar.
    • Haga clic en siguiente.
    • Haga clic en Finalizar

    • En la versión 2010 accedemos a Archivo->Abrir->Importar.

    1

    • En la ventana emergente elegimos exportar a un archivo

    2

    • Elegimos el tipo de archivo Valores separados por comas(Windows)

    3

    • Elegimos el tipo de datos que queremos exportar, en este caso los contactos.

    4

    • Por último asignamos el nombre y la ubicación de los datos a exportar como hemos vistos en las versiones 2003 y 2007.

    Importar desde Windows Live Hotmail

    • Accedemos desde nuestro terminal con Windows Phone 7, a Windows Live Hotmail.
    • Iniciamos sesión.
    • Accedemos a la sección Contactos.
    • Hacemos clic sobre Agregar personas.

    5

    • Seguidamente podemos ver los diferentes medios desde donde podemos realizar la importación de nuestros contactos(Facebook,My Spaces,Outlook,etc..)

    6

    • Seleccionamos lógicamente Outlook. Para más tarde seleccionar el archivo que hemos exportado desde Outlook.

    7

    • Una vez importados para realizar la sincronización con Windows Phone 7. Nos situamos en Configuración->Cuentas de correo electrónico. Presionamos sobre nuestra cuenta Windows Live Hotmail y aparecerá la opción Sincronizar en la pantalla del terminal.

    Conseguido!!!

    Exportar citas del Calendario de Outlook

    • Nos situamos en la sección Calendario de Outlook, seguidamente vamos a guardar el calendario que nos convenga sincronizar con Windows Phone 7. Presionamos sobre Archivo->Guardar Calendario. Finalmente otorgamos el nombre y la ubicación que deseemos, pero el formato a de ser .ics (formato que soporta Windows Live Hotmail).

    8

    • Aparecerá un mensaje para seleccionar las fechas de las citas del calendario que queremos exportar.

    11

    • Para exportar el calendario completo debemos seleccionas las opciones Calendario Completo y Detalles Completos.

    12

    Importar Calendario desde Windows Live Hotmail

    • Abrimos la sesión de Windows Live Hotmail, accedemos a la sección Calendario.
    • Presionamos sobre el apartado Suscribirse.

    9

    • Elegimos la opción Importar de un archivo ICS. Seleccionamos el archivo exportado desde outlook y nombramos el calendario que vamos a importar.

    10

    Y tendremos el calendario importado, ahora realizamos la sincronización de el calendario en el terminal. Nos situamos en Configuración->Cuentas de correo electrónico. Presionamos sobre nuestra cuenta Windows Live Hotmail y aparecerá la opción Sincronizar en la pantalla del terminal.

    De esta forma podemos utilizar nuestros contactos y citas de Outlook desde Windows Phone 7 utilizando como pasarela Windows Live Hotmail.

    Recomendaciones para crear Interfaz de usuario en Silverlight (XAML)

    Los desarrolladores que empezáis a elaborar vuestros primeros proyectos y desarrollos en Silverlight. Deseo haceros llegar una serie de recomendaciones que son aconsejables a la hora de trabajar con el XAML de la interfaz de usuario

    1. Utiliza en todo momento estilos y plantillas. Estos elementos te ayudarán a simplificar tu desarrollo, evitando repeticiones de código y pérdida de tiempo.
    2. Agrega los estilos y plantillas en un archivo independiente, de este modo podrás compartir dichos elementos a través en toda tu aplicación. Si son específicas de una sola página, agregarlos en los recursos de dicha página.
    3. Elimina los estilos plantillas y animaciones innecesarias, estos elementos retrasan la carga de la aplicación.
    4. No utilice los espacios de nombres innecesarios "xmlns" en el archivo XAML. Esto sobrecarga el tiempo de carga de la página de Silverlight.
    5. Utiliza un nombre significativo en cada uno de los prefijos del espacio de nombres de "xmlns". Por ejemplo: xmlns:MapasLogistica es más significativo e identificables que xmlns:ML. Esto evita las múltiples declaraciones de espacios de nombres en el futuro.
    6. Cuando agreguéis un control que no tiene elementos en su interior o sea un control padre sin hijos, mejor cerrarlo con la etiqueta "/ >" en lugar de la etiqueta de cierre (</TAG>). Esto otorga limpieza a tu código XAML y facilidad de lectura por parte de otros colaboradores dentro de tu proyecto.
    7. Incluir comentarios en XAML siempre ayuda. Esto te será útil en un futuro a la hora de revisar el código que no has tocado durante un tiempo.También ayuda a personas que colaboran en tu proyecto(Diseñadores,Tester,etc.) a una fácil comprensión y con ello mejoras el tiempo de desarrollo de Software.
    8. Siempre debemos intentar utilizar el objeto Grid como el panel padre de tu aplicación.El  Grid tiene un unas características de  flexibilidad que nos hacen la vida más sencilla en cuanto a interfaz de usuario se refiere.
    9. No debes de utilizar paneles adicionales (por ejemplo, Grid, StackPanel, Wrappanel etc.) a menos que sea necesario, estos elementos necesitan un tiempo de carga mayor que otros objetos simples que ofrece Silverlight.
    10. Utilice la propiedad Visibility de los controles en lugar de la propiedad de Opacity, si lo que deseamos es ocultar el contenido de los mismos. Si otorgamos el valor cero a la propiedad Opacity de un objeto, dicho elemento no estará visible dentro de la interfaz de usuario, pero ocupa espacio en la memoria y en la interfaz de usuario.Por otro lado, la propiedad Visibility contrae el control en la interfaz de usuario, ocupando menos espacio en memoria y a su vez dejando que otros controles utilicen el espacio que este ocupa dentro de la interfaz de usuario.
    11. Siempre que vayas a diseñar la interfaz de usuario en especial animaciones utiliza Expression Blend, esta herramienta no solo te ayudará en la creación de las mismas, si no que además te permite utilizar un sin fin de opciones en un solo clic sin necesidad de incorporar código de forma manual.

    Estas son mis recomendaciones, seguro que habrá muchas más por lo que espero vuestra colaboración para ampliar la lista.

    Posted: 15/11/2010 12:48 por RAÚL MAYO | con 3 comment(s)
    Archivado en:
    Material Webcast Movilízate con WP7 & Silverlight 4

    El Webcast que realice el 10 de Noviembre sobre desarrollo de aplicaciones basadas en Silverlight para una posterior implementación en Windows Phone 7.

    Ya tenéis disponible tanto la grabación del webcast, la presentación y las demos, solo tendréis que hacer clic sobre los diferentes iconos para acceder al contenido de los mismos.

    1 (21) 1 (13) 1 (4)

    Tutorial “Enrutamiento con Bing Maps y Silverlight”

    Quién más o quien menos alguna vez a dedicado un espacio de tiempo ha localizar un local,un lugar, un punto de interés o a preparar una ruta a la hora de viajar. Por otro lado son cada vez más las empresas que utilizan la geolocalización como instrumento de trabajo, es por este motivo que planteo la segunda parte de las opciones que nos ofrece el API de Bing Maps. En este artículo vamos a utilizar por un lado la geolocalización que he especificado en artículos anteriores y además vamos aprovechar el servicio de enrutamiento que pone a disposición de los desarrolladores Microsoft. De este modo podemos realizar una ruta entre los respectivos puntos que hemos geolicalizado previamente.

    Para empezar deberéis asociar una cuenta Live ID y la URL de la página en la que vamos a utilizar la API de Bing Maps. Podéis ver los pasos que tenéis que seguir para disfrutar del API de Bing Maps aqui.

    Una vez realizada la asociación, vamos a crear una una nueva aplicación Silverlight desde Visual Studio 2010. Para ello elegimos la plantilla Silverlight Businees Application, elegimos el nombre que queremos para dicho proyecto así como la ubicación del mismo como podemos ver a continuación:

    image

    Abrimos la página que se carga por defecto en el marco de trabajo de dicha aplicación(Home.Xaml), esta se encuentra ubicada dentro de la carpeta Views del lado del cliente.

    Lo primero vamos añadir el servicio de geolocalización a nuestro proyecto. Para ello presionamos con el botón derecho sobre la carpeta Refereces. Elegimos Add Service Reference. En la ventana emergente, debemos introducir en la sección Address la siguiente URL del servicio de Geolocalización (http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc). Presionamos sobre el botón Go para comprobar que la comunicación con el servicio se realiza de forma correcta. El servicio lo identificaremos con el nombre GeocodeService que debemos introducirlo en el apartado NameSpace:

    image

    Presionamos en OK y ya tenemos preparado el servicio para su posterior utilización.

    Seguidamente vamos añadir los credenciales de la API de Bing Maps en los recursos de aplicación y sobre el propio objeto Map.

    Abrimos App.xaml, dentro de la etiqueta <ResourceDictionary>

    introducimos <sys:String x:Key="MisCredenciales">Clave Cuenta Bing Maps</sys:String>

    siendo el resultado final de dicho archivo el siguiente:

    1.    <Application
    2. x:Class="Rutas.App"
    3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    5. xmlns:app="clr-namespace:Rutas"
    6. xmlns:sys="clr-namespace:System;assembly=mscorlib"
    7. Startup="Application_Startup"
    8. UnhandledException="Application_UnhandledException">
    9.  
    10.     <Application.Resources>
    11.         <ResourceDictionary>
    12.             <ResourceDictionary.MergedDictionaries>
    13.                 <ResourceDictionary Source="Assets/Styles.xaml"/>
    14.                 <ResourceDictionary>
    15.                     <app:ResourceWrapper x:Key="ResourceWrapper" />
    16.                     <app:NotOperatorValueConverter x:Key="NotOperatorValueConverter" />
    17.                     <sys:String x:Key="MisCredenciales">Clave Cuenta Bing Maps</sys:String>
    18.                 </ResourceDictionary>
    19.             </ResourceDictionary.MergedDictionaries>
    20.                         </ResourceDictionary>
    21.     </Application.Resources>
    22.  
    23. </Application>

    Más adelante utilizaremos dichos credenciales en el objeto Map como un recurso del proyecto.

    Ahora vamos a centrarnos en la interfaz de usuario, primeramente vamos referenciar las librerías de Bing Maps( que previamente hemos añadido, puedes ver aquí donde encuentran las misma) para poder realizar las diferentes acciones de Geocodificación. Dentro de la etiqueta <Page> introducimos la referencia:

    1. xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

    Seguidamente, vamos a definir la estructura de los diferentes objetos que incluiremos dentro de la interfaz de usuario de Home.xaml, para ello añadimos el siguiente fragmento de código:

    1. <Grid x:Name="LayoutRoot">
    2.         <Grid.ColumnDefinitions>
    3.             <ColumnDefinition Width="271*"/>
    4.             <ColumnDefinition Width="100*"/>
    5.         </Grid.ColumnDefinitions>
    6.         <Grid.RowDefinitions>
    7.             <RowDefinition Height="255*"/>
    8.             <RowDefinition Height="45*"/>
    9.         </Grid.RowDefinitions>
    10.         <map:Map x:Name="mapa" Center="40.225,-1.794" ZoomLevel="6" Mode="Road" Grid.Row="0" Grid.ColumnSpan="2">
    11.             <map:Map.CredentialsProvider>
    12.                 <map:ApplicationIdCredentialsProvider ApplicationId="{StaticResource MisCredenciales}"/>
    13.             </map:Map.CredentialsProvider>
    14.         </map:Map>
    15.         <TextBox x:Name="txbPI" Grid.Row="1" Grid.Column="0" Margin="10" BorderBrush="Black" FontSize="21.333" FontFamily="Verdana"/>
    16.         <Button x:Name="btnGeocode" Content="Añadir Localizador" Grid.Row="1" Grid.Column="1" Margin="5" Click="btnGeocode_Click"/>
    17.     </Grid>

    Como podéis observar hemos añadido el objeto Map que se encargará de representar el mapa donde se localizarán los diferentes puntos que el usuario busque. También hemos añadido un TextBox para que el usuario pueda introducir los lugares ha buscar y un botón que se encargará de realizar las diferentes acciones para representar los diferentes lugares en el objeto Map. Para generar el evento del botón btnGeocode, presionamos doble click cobre el mismo. De este modo nos desplazaremos al código Behin de la aplicación (Home.xaml.cs). Dentro de dicho evento debemos introducir el siguiente fragmento de código:

    1. private void btnGeocode_Click(object sender, System.Windows.RoutedEventArgs e)
    2.         {
    3.             GeocodeService.GeocodeServiceClient geocodeClient = new GeocodeService.GeocodeServiceClient
    4.  
    5. ("CustomBinding_IGeocodeService");
    6.  
    7.             GeocodeService.GeocodeRequest resquest = new GeocodeService.GeocodeRequest();
    8.             resquest.Query = txbPI.Text;
    9.             resquest.Credentials = new Microsoft.Maps.MapControl.Credentials();
    10.             resquest.Credentials.ApplicationId = App.Current.Resources["MisCredenciales"] as string;
    11.  
    12.             geocodeClient.GeocodeCompleted += new EventHandler<GeocodeService.GeocodeCompletedEventArgs>(geocodeClient_GeocodeCompleted);
    13.             geocodeClient.GeocodeAsync(resquest);
    14.  
    15.         }

    Por otro lado debemos de referenciar las librería de Bing Maps dentro del código Behind para aprovechar su funcionalidad, para ello añadimos la siguiente directiva:

    1. using Microsoft.Maps.MapControl;

    Como podemos observar creamos un objeto GeocodeServiceClient, que nos permite comunicar la aplicación con el servicio GeocodeService. Dicho servicio requiere del Objeto GeocodeRequest que envía la petición de un nuevo localizador a través del texto introducido en el TextBox. Pero este acceso al servicio no sería posible si no enviaríamos los credenciales de la cuenta Bing Maps. Por último la petición al servicio se ha de realizar de forma asíncrona, cuando la petición regresa la controlamos a través del controlador de eventos geocodeClient_GeocodeCompleted.

    Ahora vamos a introducir el  evento citado con anterioridad. En el, obtenemos un array con una serie de coincidencias con el texto introducido en el TextBox. Como solo nos interesa el primer elemento, a través de LINQ obtenemos ese primer elemento. Tomamos la longitud y latitud de ese elemento, creamos en la interfaz de usuario un nuevo localizador. El último paso es ofrecer la mejor vista de ese localizador por lo que el objeto mapa realizará un Zoom sobre dicho punto de interés a fin de mejorar la experiencia de usuario.

    1. private void geocodeClient_GeocodeCompleted(object sender, GeocodeService.GeocodeCompletedEventArgs e)
    2.         {
    3.             GeocodeService.GeocodeResponse response = e.Result;
    4.             if (response.Results.Count > 0)
    5.             {
    6.                 GeocodeService.GeocodeResult result = response.Results.First();
    7.                 if (result.Locations.Count > 0)
    8.                 {
    9.                     Pushpin pushpin = new Pushpin();
    10.                     Location location = new Location(result.Locations.First().Latitude, result.Locations.First().Longitude);
    11.                     pushpin.Location = location;
    12.                     mapa.Children.Add(pushpin);
    13.                     mapa.SetView(result.BestView);
    14.                     
    15.                 }
    16.             }
    17.         }

    Ejecutamos la aplicación, accedemos a la sección Logística desde el menú de Navegación. Introducimos en el TextBox por ejemplo Cein, Navarra y el resultado es el siguiente:

     

    image

    En esta parte del articulo vamos desarrollar la realización de rutas entre lo diferentes puntos que interesen al usuario.Empezamos haciendo clic con el botón derecho sobre la carpeta Reference, elegimos Add Service Reference.En la ventana emergente, debemos introducir en la sección Address la siguiente URL del servicio de enrutamiento (http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc ). Presionamos sobre el botón Go para comprobar que la comunicación con el servicio se realiza de forma correcta. El servicio lo identificaremos con el nombre RouteService que debemos introducirlo en el apartado NameSpace:

    image

    Seguidamente vmos a crear una clase con los parámetros que necesita el servicio para su correcto funcionamiento. Realizamos clic con el botón derecho sobre nuestro proyecto del lado del cliente. Elegimos Añadir->Nuevo elemento, de las plantillas que Visual Studio 2010 nos ofrece por defecto, elegimos Clase, nombrándola como UbicacionEntrega.cs.

    image

    Dentro de la misma incluiremos el siguiente código:

    1. using System;
    2. using System.Net;
    3. using System.Windows;
    4. using System.Windows.Controls;
    5. using System.Windows.Documents;
    6. using System.Windows.Ink;
    7. using System.Windows.Input;
    8. using System.Windows.Media;
    9. using System.Windows.Media.Animation;
    10. using System.Windows.Shapes;
    11. using Microsoft.Maps.MapControl;
    12.  
    13. namespace SilverlightBusinessApplication
    14. {
    15.     public class UbicacionEntrega
    16.     {
    17.         public string Address { get; set; }
    18.  
    19.         public Location Location { get; set; }
    20.  
    21.     }
    22. }

    El siguiente paso que vamos a dar, es la actualización del interfaz de usuario. Tenemos que introducir nuevos elemento y cambiar la distribución de los anteriores. El resultado de la nueva interfaz de usuario es la siguiente:

     

    1. <Grid x:Name="LayoutRoot">
    2.         <Grid.ColumnDefinitions>
    3.             <ColumnDefinition Width="271*"/>
    4.             <ColumnDefinition Width="100*"/>
    5.         </Grid.ColumnDefinitions>
    6.         <Grid.RowDefinitions>
    7.             <RowDefinition Height="188*"/>
    8.             <RowDefinition Height="67*"/>
    9.             <RowDefinition Height="45*"/>
    10.         </Grid.RowDefinitions>
    11.         <map:Map x:Name="mapa" Center="40.225,-1.794" ZoomLevel="6" Mode="Road" Grid.RowSpan="2">
    12.             <map:Map.CredentialsProvider>
    13.                 <map:ApplicationIdCredentialsProvider ApplicationId="{StaticResource MisCredenciales}"/>
    14.             </map:Map.CredentialsProvider>
    15.             <map:MapLayer x:Name="routeLayer"/>
    16.         </map:Map>
    17.         <TextBox x:Name="txtAddress" Grid.Row="2" Margin="10,10,10,68" BorderThickness="3" Background="White" />
    18.         <Button x:Name="btnGeoCode" Content="Añadir Localizador" Grid.Row="2" Grid.Column="1" Margin="5" Click="btnGeocode_Click"/>
    19.         <TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Text="Entregas" TextWrapping="Wrap" Grid.Column="1" />
    20.         <ListBox x:Name="lbxDestinations" Margin="5,20,8,7" Grid.Column="1" Grid.RowSpan="1">
    21.             <ListBox.ItemTemplate>
    22.                 <DataTemplate>
    23.                     <StackPanel>
    24.                         <TextBlock Text="{Binding Address}" TextWrapping="Wrap"/>
    25.                         <StackPanel Orientation="Horizontal">
    26.                             <Button Content="Subir" Tag="{Binding}" x:Name="ButtonUp" Click="ButtonUp_Click"/>
    27.                             <Button Content="Bajar" Tag="{Binding}" x:Name="ButtonDown" Click="ButtonDown_Click"/>
    28.                             <Button Content="Borrar" Tag="{Binding}" x:Name="ButtonRemove" Click="ButtonRemove_Click"/>
    29.                         </StackPanel>
    30.                     </StackPanel>
    31.                 </DataTemplate>
    32.             </ListBox.ItemTemplate>
    33.         </ListBox>
    34.         <StackPanel Grid.Column="1" Grid.Row="1" Orientation="Vertical" d:LayoutOverrides="Height">
    35.             <CheckBox x:Name="cbxTraffic" Content="Evitar Tráfico"/>
    36.             <Button x:Name="btnCalculateRoute" Click="btnCalculateRoute_Click" Height="22" Content="Calcular Ruta" Margin="5,5,5,0"/>
    37.             <TextBlock x:Name="txtTotalTime" Text="Tiempo Total:" Margin="5,15,5,0" TextWrapping="Wrap"
    38.                        FontSize="13.333" HorizontalAlignment="Center" Width="337" Height="49" />
    39.            
    40.         </StackPanel>
    41.     </Grid>

    Hemos empezado por un cambio de la distribución de los elementos dentro del <Grid> principal. Luego hemos añadido un objeto ListBox, dentro del mismo hemos definido una plantilla para cada elemento que se agregue al ListBox. Dicha plantilla se compone del nombre de la Localización (que es obtenido directamente de una colección de elementos)y tres botones. Dos para desplazar el localizador entre los diferentes Items del ListBox y el tercero para borrar el localizador.

    También hemos añadido un objeto CheckBox para que el usuario pueda evitar los atascos de tráfico que pueda haber en la ruta elegida. Un botón que será el disparador de las acciones de cálculo de ruta. El último objeto es un TextBlock quese encarga de mostrar al usuario el tiempo que va tardar en realizar la ruta entre los diferentes localizadores que previamente ha seleccionado.

    Un elemento que hemos introducido y que no he nombrado pero si destacado es <map:MapLayer x:Name="routeLayer"/>. Dicho elemento nos permitirá la representación de la ruta, sin tener que añadir esta como un hijo del objeto Map. Esto otorga una independencia a la hora de mostrar, ocultar o actualizar la ruta. Ya que si el usuario realiza una serie de comportamientos la ruta se redibuja nuevamente y no confunde al usuario.

     

    El siguiente paso es añadir las nuevas funciones del botón Añadir Localizador. Para ello añadimo dentro del constructor de logistica.xaml.cs una colección que es del tipo UbicacionEntrega y un miembro que guarda la respuesta del servicio.

    1. private ObservableCollection<UbicacionEntrega> _locations = new ObservableCollection<UbicacionEntrega>();
    2.         private RouteService.RouteResponse _currentRoute;

    También añadimos la siguiente referencia:

    1. using System.Collections.ObjectModel;

    Dentro del evento click del Botón que realiza la inclusión de nuevos localizadores, vamos a incluir el borrado de la capa de la que hemos hablado con anterioridad, debido a que se va dibujar una nueva cada vez que añadimos un nuevo localizador. También hemos añadido la cultura con la que se va mostrar la interfaz de usuario. Por último pasamos los credenciales para todos los objetos incluidos en Map. El resultado final del evento click del botón es el siguiente:

    1. private void btnGeocode_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             routeLayer.Children.Clear();//borra el hijo que en ese momento esta representado en la capa
    4.  
    5.             GeocodeService.GeocodeServiceClient geocodeClient = new GeocodeService.GeocodeServiceClient
    6.  
    7.             ("CustomBinding_IGeocodeService");
    8.  
    9.             GeocodeService.GeocodeRequest resquest = new GeocodeService.GeocodeRequest();
    10.             resquest.Culture = mapa.Culture;//otorga la cultura del S.O. al mapa
    11.             resquest.Query = txtAddress.Text;
    12.             resquest.Credentials = new Microsoft.Maps.MapControl.Credentials();//pasamos los credenciales
    13.             resquest.Credentials.ApplicationId = App.Current.Resources["MisCredenciales"] as string;
    14.  
    15.             geocodeClient.GeocodeCompleted += new EventHandler<GeocodeService.GeocodeCompletedEventArgs>(geocodeClient_GeocodeCompleted);
    16.             geocodeClient.GeocodeAsync(resquest);
    17.         }

    En el controlado de eventos creamos una variable del tipo de la clase con los parámetros obtenidos en la interfaz de usuario. A la etiqueta del localizador le introducimos los valores introducidos con anterioridad. Por último añadimos el localizador a la colección. Siendo este el aspecto final:

    1. private void geocodeClient_GeocodeCompleted(object sender, GeocodeService.GeocodeCompletedEventArgs e)
    2.         {
    3.             GeocodeService.GeocodeResponse response = e.Result;
    4.             if (response.Results.Count > 0)
    5.             {
    6.                 GeocodeService.GeocodeResult result = response.Results.First();
    7.                 if (result.Locations.Count > 0)
    8.                 {
    9.                     Pushpin pushpin = new Pushpin();
    10.                     Location location = new Location(result.Locations.First().Latitude, result.Locations.First().Longitude);
    11.                     pushpin.Location = location;
    12.                     mapa.Children.Add(pushpin);
    13.                     mapa.SetView(result.BestView);
    14.                     UbicacionEntrega dl = new UbicacionEntrega() { Address = this.txtAddress.Text, Location = location };
    15.                     //Creamos una variable con los parametros de la clase obtenidos de los objetos de la
    16.                     //interfaz de usuario
    17.                     pushpin.Tag = dl;//introducimso el valor de la etiqueta del localizador
    18.                     this._locations.Add(dl);//añadimos el localizador a la colección de localizadores
    19.                 }
    20.             }
    21.         }

    Vamos a trabajar con los tres botones que pueden tener cada elemento que se añade al Listbox.

    Los botones de desplazamiento (Subir, Bajar) del localizador tienen el mismo comportamiento, salvo la posición que ha de ocupar el elemento cuando presionamos alguno de los citados botones.

     

    1. private void ButtonUp_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             Button btnSender = sender as Button;
    4.             UbicacionEntrega dl = btnSender.Tag as UbicacionEntrega;
    5.             SubirLocalizador(dl);
    6.  
    7.         }
    8.  
    9.         private void ButtonDown_Click(object sender, RoutedEventArgs e)
    10.         {
    11.             Button btnSender = sender as Button;
    12.             UbicacionEntrega dl = btnSender.Tag as UbicacionEntrega;
    13.             BajarLocalizador(dl);
    14.         }

    En el evento click de los botones, creamos una variable de tipo botón para obtener todo su contenido a través de la propiedad etiqueta. Finalmente enviamos a los respectivos métodos la variable como UbicacionEntrega.

     

    1. private void SubirLocalizador(UbicacionEntrega dl)
    2.         {
    3.             MoverLocalizador(dl, -1);
    4.         }
    5.         private void BajarLocalizador(UbicacionEntrega dl)
    6.         {
    7.             MoverLocalizador(dl, 1);
    8.         }
    9.         private void MoverLocalizador(UbicacionEntrega dl, int direction)
    10.         {
    11.             BorrarRuta();
    12.             if (this._locations.Count > 1)
    13.             {
    14.                 int origIndex = this._locations.IndexOf(dl);
    15.                 this._locations.Remove(dl);
    16.                 this._locations.Insert(origIndex + direction, dl);
    17.             }
    18.         }
    19.         private void BorrarRuta()
    20.         {
    21.             this._currentRoute = null;
    22.             routeLayer.Children.Clear();
    23.             this.txtTotalTime.Text = "";
    24.         }

    En función de si queremos subir o bajar el localizador en el Listbox, llamaremos a un método u otro. Ambos métodos llaman a su vez a MoverLocalizador. Primeramente borra la ruta que hay reflejada en el mapa, así como el tiempo en que se tarda en realizar la ruta. Seguidamente se comprueba que haya más de un elemento en la colección. Si es así, borra el elemento de la lista y sitúa la copia del elemento que está en memoria en la posición correspondiente.

    Ahora vamos con el botón de eliminación de un localizador. En el evento click de botón a eliminar en primera instancia elimina la ruta dibujada sobre el mapa. Seguidamente borra el localizador de la colección. Finalmente busca el localizador en el objeto Mapa y es borrado de la interfaz de usuario.

    1. private void ButtonRemove_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             Button btnSender = sender as Button;
    4.             UbicacionEntrega dl = btnSender.Tag as UbicacionEntrega;
    5.             BorrarRuta();//elimina la ruta de la Interfaz de Usuario
    6.             //quitar elemento de la colección
    7.             this._locations.Remove(dl);
    8.             //buscar el marcador
    9.             var pushpinsToDelete = mapa.Children.OfType<Pushpin>().Where(x => x.Location == dl.Location);
    10.             //borrar el marcador de la interfaz usuario
    11.             pushpinsToDelete.ToList().ForEach(x => mapa.Children.Remove(x));
    12.         }

     

    Por último vamos a calcular y representar la ruta en la interfaz de usuario.Empezando por generar el evento clic del botón “Calcular Ruta”, para ello realizamos doble clic sobre este en el área de diseño de Logistica.xaml.

    Nos situamos en el evento click del botón que se encarga de calcular las diferentes rutas del departamento de logística situado en Logistica.xaml.cs. La primera parte del código que vamos a introducir en el mencionado evento, es esencialmente igual, que la que hemos utilizado para el botón que añade localizadores. La única diferencia es que en vez de usar el servicio GeocodeService utilizamos el servicio RouteService

    1. private void btnCalculateRoute_Click(object sender, RoutedEventArgs e)
    2.         {
    3.  
    4.             routeLayer.Children.Clear();
    5.  
    6.  
    7.             RouteService.RouteServiceClient routeServiceClient = new RouteService.RouteServiceClient("CustomBinding_IRouteService");
    8.             routeServiceClient.CalculateRouteCompleted += new EventHandler<RouteService.CalculateRouteCompletedEventArgs>(routeServiceClient_CalculateRouteCompleted);
    9.  
    10.             RouteService.RouteRequest routeRequest = new RouteService.RouteRequest();
    11.             routeRequest.Culture = mapa.Culture;
    12.             routeRequest.Credentials = new Credentials();
    13.             routeRequest.Credentials.ApplicationId = App.Current.Resources["MisCredenciales"] as string;
    14.  
    15.            
    16.  
    17.         }

    Inmediatamente después del evento click con el que hemos trabajado vamos a implementar en controlador de eventos routeServiceClient_CalculateRouteCompleted, añadiendo el siguiente fragmento de código:

     

    1. private void routeServiceClient_CalculateRouteCompleted(object sender, RouteService.CalculateRouteCompletedEventArgs e)
    2.         {
    3.             if (e.Error == null)
    4.             {
    5.                 long timeInSeconds = e.Result.Result.Summary.TimeInSeconds;
    6.                 //obtiene el tiempo de la ruta del servicio
    7.                 TimeSpan t = new TimeSpan(0, 0, int.Parse(timeInSeconds.ToString()));
    8.                 this.txtTotalTime.Text = string.Format("Tiempo Estimado: {0}", t.ToString());
    9.                 //da formato a la variable del tiempo de la ruta y lo incluye en el objeto
    10.                 //que lo mostrará en la Interfaz de Usuario
    11.                 DrawRoute(e);
    12.                 //llamada al método que dibuja la ruta
    13.  
    14.                 this._currentRoute = e.Result;
    15.             }
    16.         }

    Volvemos al evento clic del botón de cálculo de ruta. En el introducimos las opciones de cálculo de ruta que vamos a pedir al servicio. Esta petición va a ser para que la ruta se calcule a través de puntos (Localizadores).

     

    1. routeRequest.Options = new RouteService.RouteOptions();
    2.             routeRequest.Options.RoutePathType = RouteService.RoutePathType.Points;
    3.  
    4.             routeRequest.ExecutionOptions = new RouteService.ExecutionOptions();
    5.             routeRequest.ExecutionOptions.SuppressFaults = true;

    Seguidamente, vamos a contemplar la opción del control de tráfico, que en el interfaz de usuario ofrecemos al usuario final. Introducimos el siguiente código dentro del evento click del botón:

     

    1. if (this.cbxTraffic.IsChecked.Value)
    2.             {
    3.                 routeRequest.Options.TrafficUsage = RouteService.TrafficUsage.TrafficBasedRouteAndTime;
    4.             }
    5.             else
    6.             {
    7.                 routeRequest.Options.TrafficUsage = RouteService.TrafficUsage.None;
    8.             }

    Ahora que tenemos todas las opciones en nuestro objeto RouteRequest, es momento de añadir los localizadores como puntos para realizar el cálculo de la ruta(todo ello dentro del evento clic usado con anterioridad). El siguiente código establece las propiedades de los puntos de la ruta como una ObservableCollection de puntos. Además usa LINQ para recorrer todos los elementos contenidos en la lista _locations (que hemos definido en el constructor). Finalmente pasaremos todos los elementos al método GeocodeResultToWaypoint.

     

    1. routeRequest.Waypoints = new System.Collections.ObjectModel.ObservableCollection<RouteService.Waypoint>();
    2.             this._locations.ToList().ForEach(x => routeRequest.Waypoints.Add(GeocodeResultToWaypoint(x)));

    El último fragmento de código que vamos a incluir en el evento click del botón, es la llamada asíncrona al método RouteRequest del servicio de cálculo de ruta de Bing Maps pasándole el objeto routeRequest, como podemos observar a continuación:

    1. routeServiceClient.CalculateRouteAsync(routeRequest);

    El siguiente paso es crear el método GeocodeResultToWaypoint que convierte el objeto UbicacionEntrega en el objeto Waypoint, que son los puntos necesarios para crear y calcular una ruta:

     

    1. private RouteService.Waypoint GeocodeResultToWaypoint(UbicacionEntrega deliverylocation)
    2.         {
    3.             RouteService.Waypoint waypoint = new RouteService.Waypoint();
    4.             waypoint.Description = deliverylocation.Address;
    5.             waypoint.Location = new Location();
    6.             waypoint.Location.Latitude = deliverylocation.Location.Latitude;
    7.             waypoint.Location.Longitude = deliverylocation.Location.Longitude;
    8.             return waypoint;
    9.         }

    El último método que nos queda por implementar es el que se encarga de dibujar en la capa del objeto mapa la ruta para los diferentes localizadores. Añadimos el siguiente fragmento de código:

    1. private void DrawRoute(SilverlightBusinessApplication.RouteService.CalculateRouteCompletedEventArgs e)
    2.         {
    3.             if (e.Result.Result.Legs.Count > 0)
    4.             {
    5.                 //creamos un objeto MapPolyline llamado routeLine
    6.                 //y establecemos sus propiedades visuales
    7.                 Color routeColor = Colors.Blue;
    8.                 SolidColorBrush routeBrush = new SolidColorBrush(routeColor);
    9.                 MapPolyline routeLine = new MapPolyline();
    10.                 routeLine.Locations = new LocationCollection();
    11.                 routeLine.Stroke = routeBrush;
    12.                 routeLine.Opacity = 0.65;
    13.                 routeLine.StrokeThickness = 5.0;
    14.  
    15.                 double distance = e.Result.Result.Summary.Distance;
    16.                 long seconds = e.Result.Result.Summary.TimeInSeconds;
    17.  
    18.                 TimeSpan time = new TimeSpan(0, 0, int.Parse(seconds.ToString()));
    19.  
    20.                 //el mapa recupera una serie de puntos entre los localizadores
    21.                 //y los representa como una linea
    22.                 foreach (Location p in e.Result.Result.RoutePath.Points)
    23.                 {
    24.                     routeLine.Locations.Add(new Location(p.Latitude, p.Longitude));
    25.                 }
    26.                 //la linea es dibujada en la capa del mapa
    27.                 routeLayer.Children.Add(routeLine);
    28.                 //centramos el mapa acorde a la ruta, creando un rectangulo delimitador
    29.                 LocationRect rect = new LocationRect(routeLine.Locations[0], routeLine.Locations[routeLine.Locations.Count - 1]);
    30.  
    31.                 //definimos la vista de mapa utilizando los límites del rectángulo anterior
    32.                 mapa.SetView(rect);
    33.             }
    34.  
    35.         }

    Por último en el evento de carga de la página vamos establecer el origen de los elementos del ListBox como la colección _locations, aunque previamente tenemos que generarlo en logística.xaml como podemos observar en la siguiente imagen:

     

    image

    En el código Behind del citado evento incluiremos el siguiente fragmento de código:

     

    1. private void Page_Loaded(object sender, RoutedEventArgs e)
    2.         {
    3.             this.lbxDestinations.ItemsSource = this._locations;
    4.  
    5.         }

    Ejecutamos la aplicación ( F5 ), introducimos los diferentes puntos de entrega que queremos añadir a la ruta.

    image 

    Presionamos sobre calcular Ruta y podemos ver como la ruta se dibuja en el mapa y calcula el tiempo estimado de la misma.

    image

    Podemos personalizar las diferentes rutas con las opciones que ofrecemos al usuario final.

    Podéis ver todo el material de este tutorial aquí (recordar debereis incluir el ID de Bing Maps en App.xaml, para que funcione de forma correcta objeto Mapa).

    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

    Posted: 14/10/2010 15:24 por RAÚL MAYO | con 1 comment(s)
    Archivado en:
    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.

    Taller Desarrollo de Aplicaciones de Negocio basadas en Silverlight 4

    Desde los centros de Excelencia Software hemos publicado el nuevo catálogo de Talleres y Jornadas CES 2º Semestre 2010. Entre los que se encuentra el taller que voy a impartir los próximos 25 y 26 de Octubre. En el realizaré laboratorios centrados en el Desarrollo de Aplicaciones de Negocio basadas en Silverlight 4, Windows Phone 7, Bing Maps, Azure, etc.. Si deseas conocer más detalles sobre dicho taller puedes acceder al mismosdesde aquí.

    Por otro lado también se van a desarrollar talleres en los Centros de Excelencia Software Microsoft en colaboración con los profesionales de Plain Concepts. La temática de estos versan sobre tecnologías como ASP.NET, Ajax,MS Dynamics ,Metodologías Ágiles, etc..

    Problemas al Implementar un servicio WCF en WP7

    Al desarrollar el código del ejemplo del artículo anterior, tuve un problema a la hora de implementar el servicio WCF en mi aplicación WP7. El error que Visual Studio 2010 me mostraba era el siguiente:

    “custom tool error failed to generate code for the service reference”, mirando y buscando por la red encontré una solución que propone Michael B McLaughlin desde su blog.

    Esencialmente lo que tenemos que hacer es abrir una consola de comando como Administrador. Acceder desde esta a la ruta C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools para 64 bit y para 32 bit C:\Program Files \Microsoft SDKs\Windows Phone\v7.0\Tools. Por último incluimos el nombre de la herramienta que va permitir que el servicio arranque y se comunique con Windows Phone 7, más el enlace del servicio que queremos usar”SlSvcUtil.exe http://localhost:56603/Service1.svc?wsdl

    image

    Al introducir en la consola de comandos C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools\SlSvcUtil.exe http://localhost:56603/Service1.svc?wsdl

    image

    Se generan los archivos que nos permitirán sin problema alguno, trabaja con el servicio de WCF en los diferentes proyectos de Windows Phone 7 que elaboremos.

    Posted: 9/9/2010 13:47 por RAÚL MAYO | con 1 comment(s)
    Archivado en: ,
    Creación y utilización de un servicio WCF en Windows Phone 7

    En estos últimos días en los que estado probando las distintas formas de obtener datos desde una fuente (Web Services,WPF, REST, etc..), he creado un servicio de WCF que más tarde he usado en Windows Phone 7.

    En este post voy a elaborar un servicio sencillo, en el que el usuario introduzca un nombre en la interfaz de WP7 esta petición es pasada al servicio que obtiene los detalles del contacto(Nombre, Apellido, teléfono,etc..) desde una base de datos (que crearemos para dicho fin). Por últimos estos detalles del contacto, son presentados en la interfaz de usuario de WP7.

    Comenzaremos creando una nueva base de datos, para ello utilizaremos en SQL Server Management Studio en mi caso la versión 2008. Realizamos clic con el botón derecho sobre Bases de Datos y seleccionamos la opción Nueva Base de Datos.

    image                    image 

     

     

    Introducimos el nombre de la base de datos,en mi caso Contactos. Expandimos la tabla recientemente creada y hacemos clic con el botón derecho sobre Tablas, seleccionando Nueva Tabla.

    image

    Ahora vamos a diseñar los campos de la tabla que tendrán las siguientes características:

    IDContacto: nchar(10) clave primeria

    Nombre:nchar(50)

    Apellidos:nchar(50)

    Teléfono:numeric(18, 0) permitir valores nulos

    Email:nchar(50) permitir valores nulos

    También nombraremos la tabla como DTContactos y rellenamos la tabla con los respectivos datos de los contactos.

    image     image    

     

     

     

     

    El siguiente paso es la creación del servicio WCF. Para ello abrimos Visual Studio 2010, seleccionamos Archivo->Nuevo Proyecto. En el área de plantillas seleccionamos WCF y elegimos la plantilla  WCF Service Application. Introducimos el nombre y la ubicación del servicio como podemos observar a continuación:

    image

    Ahora vamos añadir un nuevo elemento que nos va permitir obtener los datos desde la base de datos a través de una clase LINQ. Para ello con el botón derecho sobre el servicio(WcfService) , seleccionamos Añadir->Nuevo elemento. En la ventana emergente seleccionamos la plantilla LINQ to SQL Clasess contenida en la sección Data.

    image

    Ahora nos situamos en el explorador del servidor de Visual Studio 2010. Si no consiguiéramos ver dicho elemento lo añadiríamos desde el menú Vista->Server Explorer. Desplegamos el explorador del servidor sobre Data Connections presionamos con el botón derecho para seleccionar Añadir Conexión.

    image

    Al realizar esta acción nos encontraremos con una ventana emergente, donde podremos seleccionar la ubicación de la base de datos creada con anterioridad.

    image 

     

     

     

    Ahora desplegamos la base de datos Contactos->Tablas y arrastramos la tabla DTContacto encima de la clase de LINQ agregada en el anterior paso.

    image

    Ahora accedemos a IService1.cs y dejamos dicho elemento del siguiente modo:

     

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Runtime.Serialization;
    5. using System.ServiceModel;
    6. using System.ServiceModel.Web;
    7. using System.Text;
    8.  
    9. namespace WcfService
    10. {
    11.     
    12.     [ServiceContract]
    13.     public interface IService1
    14.     {
    15.         [OperationContract]
    16.  
    17.         List<DTContacto> EncontrarContacto(string NombreCT);
    18.     }
    19. }

     

    Como podemos observar la Interfaz Iservice1 es el contrato de servicio de WCF en el que hemos declarado una única función que toma una cadena como argumento (Nombre del contacto) y devuelve una lista de tipo DTContacto que es la clase de nuestro modelo de datos.

    Ahora accedemos a Service1.svc.cs y dejamos dicho elemento del siguiente modo:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Runtime.Serialization;
    5. using System.ServiceModel;
    6. using System.ServiceModel.Web;
    7. using System.Text;
    8.  
    9. namespace WcfService
    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.         public List<DTContacto> EncontrarContacto(string NombreCT)
    15.         {
    16.  
    17.             DataClasses1DataContext context = new DataClasses1DataContext();
    18.  
    19.             var res = from r in context.DTContactos where r.Nombre == NombreCT select r;
    20.  
    21.             return res.ToList();
    22.  
    23.         }
    24.     }
    25. }

    La clase Service1.svc.cs es el servicio encargado de implementar el contrato de servicio IService1. Dentro de dicha clase hemos definido el método EncontrarContacto. Dentro de este, hemos creado un objeto de contexto de datos, Además de una consulta LINQ que obtiene los datos de la base de datos en función del nombre introducido por el usuario. De este modo nos devuelve una lista de objeto de tipo DTContactos.

    Seguidamente nos situamos sobre el servicio Service1.svc con el botón derecho elegimos Ver en el Buscador. De esta forma podremos comprobar el correcto funcionamiento del servicio en el explorador.

    image      image

     

    Copiaremos la URL del Servicio para utilizarla a la hora de añadir el servicio en Windows Phone 7. El siguiente paso es la creación de una nueva aplicación Windows Phone 7. Para ello en visual estudio elegimos la plantilla Windows Phone Application dentro del área Silverlight For Windows Phone.

    image

    Comenzamos introduciendo la interfaz de usuario de WP7. Para ello introducimos el siguiente código en MainPage.xaml :

    1. <phone:PhoneApplicationPage
    2.     x:Class="WindowsPhoneApplication.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.     FontFamily="{StaticResource PhoneFontFamilyNormal}"
    10.     FontSize="{StaticResource PhoneFontSizeNormal}"
    11.     Foreground="{StaticResource PhoneForegroundBrush}"
    12.     SupportedOrientations="Portrait" Orientation="Portrait"
    13.     mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    14.     shell:SystemTray.IsVisible="True">
    15.  
    16.     <!--LayoutRoot contains the root grid where all other page content is placed-->
    17.     <Grid x:Name="LayoutRoot" Background="Transparent">
    18.         <Grid.RowDefinitions>
    19.             <RowDefinition Height="Auto"/>
    20.             <RowDefinition Height="*"/>
    21.         </Grid.RowDefinitions>
    22.  
    23.         <!--TitlePanel contains the name of the application and page title-->
    24.         <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
    25.            
    26.             <TextBlock x:Name="PageTitle" Text="CONTACTOS" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    27.         </StackPanel>
    28.  
    29.         <!--ContentPanel - place additional content here-->
    30.         <Grid x:Name="ContentGrid" Grid.Row="1">
    31.             <TextBox Height="79" HorizontalAlignment="Left" Margin="51,218,0,0" Name="textBox1" Text="" VerticalAlignment="Top" Width="401" />
    32.             <Button Height="70" HorizontalAlignment="Left" Margin="152,304,0,0" Name="button1" VerticalAlignment="Top" Width="160" Content="BUSCAR" Click="button1_Click" />
    33.             <TextBlock Height="57" HorizontalAlignment="Left" Margin="63,122,0,0" Name="textBlock1" Text="INTRODUZCA EL NOMBRE DEL CONTACTO A BUSCAR:" VerticalAlignment="Top" Width="398" FontFamily="Segoe WP Black" TextWrapping="Wrap" />
    34.         </Grid>
    35.     </Grid>
    36.     
    37.     
    38. </phone:PhoneApplicationPage>

    El siguiente paso añadir el servicio al proyecto WP7. Para ello hacemos clic sobre Referencias y seleccionamos Añadir Referencia de Servicio. En la ventana emergente, en el apartado Address introducimos la dirección del servicio que hemos copiado con anterioridad. Presionamos el botón GO para comprobar que se conecta correctamente al servicio. En último lugar nombraremos el espacio de nombres del servicio como ServiceReference como podemos observar a continuación:

    image

    Ahora vamos añadir una nueva página en el proyecto que mostrará los diferentes detalles del contacto una vez devuelta la petición a la base de datos. Presionamos con el botón derecho sobre el Proyecto(WindowsPhoneApplication), seleccionamos Añadir->Nuevo Elemeto. Seleccionamos la plantilla  Windows Phone Portrait Page como podemos observar en la imagen:

    image

    Dentro de la interfaz de usuario vamos a incluir un control Listbox, dentro del mismo crearemos una plantilla para incluir los diferentes objetos Texblock que enlazarán con las propiedades del elemento buscado, recuperado de la base de datos. Este es el resultado de la interfaz de usuario de Page1.xaml:

    1. <phone:PhoneApplicationPage
    2.     x:Class="WindowsPhoneApplication.Page1"
    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.     FontFamily="{StaticResource PhoneFontFamilyNormal}"
    10.     FontSize="{StaticResource PhoneFontSizeNormal}"
    11.     Foreground="{StaticResource PhoneForegroundBrush}"
    12.     SupportedOrientations="Portrait" Orientation="Portrait"
    13.     mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    14.     shell:SystemTray.IsVisible="True">
    15.     <phone:PhoneApplicationPage.Resources>
    16.         <Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
    17.             <Setter Property="Template">
    18.                 <Setter.Value>
    19.                     <ControlTemplate TargetType="ListBoxItem">
    20.                         <Grid/>
    21.                     </ControlTemplate>
    22.                 </Setter.Value>
    23.             </Setter>
    24.         </Style>
    25.         <ControlTemplate x:Key="ListBoxControlTemplate1" TargetType="ListBox">
    26.             <Grid/>
    27.         </ControlTemplate>
    28.     </phone:PhoneApplicationPage.Resources>
    29.  
    30.     <!--LayoutRoot contains the root grid where all other page content is placed-->
    31.     <Grid x:Name="LayoutRoot" Background="Transparent">
    32.         <Grid.RowDefinitions>
    33.             <RowDefinition Height="Auto"/>
    34.             <RowDefinition Height="*"/>
    35.         </Grid.RowDefinitions>
    36.  
    37.         <!--TitlePanel contains the name of the application and page title-->
    38.         <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
    39.             
    40.             <TextBlock x:Name="PageTitle" Text="Detalles Contacto" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="56" />
    41.         </StackPanel>
    42.  
    43.         <!--ContentPanel - place additional content here-->
    44.         <Grid x:Name="ContentGrid" Grid.Row="1">
    45.             <ListBox Height="503" HorizontalAlignment="Left" Margin="20,22,0,0" Name="listBox1" VerticalAlignment="Top" Width="434" >
    46.  
    47.                 <ListBox.ItemTemplate>
    48.  
    49.                     <DataTemplate>
    50.  
    51.                         <StackPanel Orientation="Vertical">
    52.                             <TextBlock Text="Nombre:" Foreground="#FFFB0000" FontSize="29.333"/>
    53.                             <TextBlock Text="{Binding Nombre}" FontSize="29.333"/>
    54.                             <TextBlock Text="Apellidos:" FontSize="29.333" Foreground="#FFFD0000"/>
    55.                             <TextBlock Text="{Binding Apellidos}" FontSize="29.333"/>
    56.                             <TextBlock Text="Teléfono" FontSize="29.333" Foreground="#FFFE0000"/>
    57.                             <TextBlock Text="{Binding Teléfono}" FontSize="29.333"/>
    58.                             <TextBlock Text="Email:" FontSize="29.333" Foreground="Red" />
    59.                             <TextBlock Text="{Binding Email}" FontSize="29.333"/>
    60.  
    61.                         </StackPanel>
    62.  
    63.                     </DataTemplate>
    64.  
    65.                 </ListBox.ItemTemplate>
    66.  
    67.             </ListBox>
    68.         </Grid>
    69.     </Grid>
    70.  
    71. </phone:PhoneApplicationPage>

     

    Seguidamente nos situamos en el evento clic del botón de busqueda, dentro de MainPage.Xaml.cs e introducimos código necesario para enviar a Page1 la cadena que el usuario ha introducido en el control habilitado para tal fin:

    1. private void button1_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             string s = textBox1.Text;
    4.  
    5.             this.Content = new Page1(s);
    6.         }

    El siguiente paso es situarnos en Page1.Xaml.cs referenciando el servicio en dicho archivo:

    1. using WindowsPhoneApplication.ServiceReference;

    Ahora realizaremos la llamada asincrona al servicio( forma normal de realizar la llamada en Silverlight), para recuperar el dato pedido, pasando al servicio el parámetro del contacto deseado. Una vez que se haya completado la llamada asincrona, el dato del contacto será devuelto e introducido en la interfaz del usuario a través del ListBox.

    1. namespace WindowsPhoneApplication
    2. {
    3.     public partial class Page1 : PhoneApplicationPage
    4.     {
    5.         public Page1(string s)
    6.         {
    7.             InitializeComponent();
    8.             Service1Client proxy = new Service1Client();
    9.  
    10.             proxy.EncontrarContactoCompleted += new EventHandler<EncontrarContactoCompletedEventArgs>(proxy_EncontrarContactoCompleted);
    11.             //controlado del evento de completar la llamada al servicio
    12.  
    13.             proxy.EncontrarContactoAsync(s);
    14.             //llamada al método del servicio de forma asincrona
    15.         }
    16.         void proxy_EncontrarContactoCompleted(object sender, EncontrarContactoCompletedEventArgs e)
    17.         {
    18.             listBox1.ItemsSource = e.Result;//carga datos del contacto en el ListBox
    19.         }
    20.     }
    21. }

    Llegados a este punto solo nos queda ejecutar el proyecto, introducir el nombre del contacto a buscar.

    image

    Obteniendo los detalles del contacto al Instante.

    image

    Alternativas a Dialog Boxes en WPF y Silverlight

    Muchas veces necesitamos abrir una serie de ventanas secundarias, para mostrar un mensaje informativo, un error, etc..Una alternativa es la utilización de los famosos Dialog Boxes, aunque esta opción no es recomendable si la aparición de estos mensajes es muy frecuente. Debido a la limitación de esta funcionalidad en XBAP de WPF y Silverlight, ahora propongo una solución alternativa para cada una de las plataformas nombradas con anterioridad.

    Para WPF la alternativa es la inclusión de un objeto PopUP, este aparecerá en la interfaz de Usuario con los elementos que nosotros queramos incluir dentro del mismo. A su vez el resto de la interfaz de Usuario será deshabilitada, de esta forma el usuario se centrará únicamente en el PopUP.

    El primer paso es crear el objeto PopUp, incluyendo dentro del mismo los correspondientes elementos:

     

    PopUp
    1. <Popup Name="Dialogo" StaysOpen="True" Placement="Center" MaxWidth="200">
    2.             <Border>
    3.                 <Border.Background>
    4.                     <LinearGradientBrush>
    5.                         <GradientStop Color="AliceBlue" Offset="1"/>
    6.                         <GradientStop Color="LightBlue" Offset="0"/>
    7.                     </LinearGradientBrush>
    8.                 </Border.Background>
    9.                 <StackPanel Margin="5" Background="White">
    10.                     <TextBlock Margin="10" TextWrapping="Wrap">
    11.                         Introduzca su Nombre de Usuario
    12.                     </TextBlock>
    13.                     <TextBox Name="txtNombre" Margin="10"/>
    14.                     <TextBlock Margin="10" TextWrapping="NoWrap">
    15.                         Introduzca su contraseña
    16.                     </TextBlock>
    17.                     <PasswordBox Name="pass"></PasswordBox>
    18.                     <StackPanel Orientation="Horizontal" Margin="10">
    19.                         <Button Click="Button_Click" Padding="3" Margin="0,0,5,0">Aceptar</Button>
    20.                         <Button Click="Button_Click_1" Padding="3">Cancelar</Button>
    21.                     </StackPanel>
    22.                 </StackPanel>
    23.             </Border>
    24.         </Popup>

     

    Como podemos observar los elementos que están incluidos en el PopUp son realmente sencillos (el grado de complejidad queda de tu mano). Simulamos un formulario de login e incluimos un botón de cancelación y de aceptación de ese Login. Por otro lado podemos ver la utilización de la propiedad StaysOpen que nos proporcionará la visibilidad del objeto al que nos estamos refiriendo, hasta que presionemos sobre alguno de los botones incluidos dentro del mismo.

    El resultado de toda la interfaz de usuario es el siguiente:

    1. <Window x:Class="PopUp.MainWindow"
    2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4.         Title="MainWindow" Height="800" Width="600">
    5.     <Grid>
    6.         
    7.         <Popup Name="Dialogo" StaysOpen="True" Placement="Center" MaxWidth="200">
    8.             <Border>
    9.                 <Border.Background>
    10.                     <LinearGradientBrush>
    11.                         <GradientStop Color="AliceBlue" Offset="1"/>
    12.                         <GradientStop Color="LightBlue" Offset="0"/>
    13.                     </LinearGradientBrush>
    14.                 </Border.Background>
    15.                 <StackPanel Margin="5" Background="White">
    16.                     <TextBlock Margin="10" TextWrapping="Wrap">
    17.                         Introduzca su Nombre de Usuario
    18.                     </TextBlock>
    19.                     <TextBox Name="txtNombre" Margin="10"/>
    20.                     <TextBlock Margin="10" TextWrapping="NoWrap">
    21.                         Introduzca su contraseña
    22.                     </TextBlock>
    23.                     <PasswordBox Name="pass"></PasswordBox>
    24.                     <StackPanel Orientation="Horizontal" Margin="10">
    25.                         <Button Name="Aceptar" Click="Aceptar_Click" Padding="3" Margin="0,0,5,0">Aceptar</Button>
    26.                         <Button Name="Cancelar" Click="Cancelar_Click" Padding="3">Cancelar</Button>
    27.                     </StackPanel>
    28.                 </StackPanel>
    29.             </Border>
    30.         </Popup>
    31.         <TextBlock x:Name="Inicio" HorizontalAlignment="Left" Height="44.4" Margin="34.2,48,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="218.4" FontFamily="Arial Black" FontSize="16" Text="Acceder a CESNAVARRA"/>
    32.         <Button Content="Acceder" Name="acesso" Height="25.2" Margin="276.6,45.177,228.6,0" VerticalAlignment="Top" Click="acesso_Click" />
    33.         <TextBlock x:Name="Mensaje" HorizontalAlignment="Left" Height="45" Margin="34.2,92.4,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="194.8" FontFamily="Arial Black" Foreground="Red"/>
    34.     </Grid>
    35. </Window>

    image

    Ahora vamos a crear en el código Behind las distintas funcionalidades del PopUp , para que este funcione de forma correcta.

    Comenzaremos con el evento del botón de acceso a nuestra aplicación, en el incluiremos el siguiente fragmento de código:

    1. private void acesso_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             DesactivarUI();
    4.         }
    5.         private void DesactivarUI()
    6.         {
    7.             MainWindow ventana = new MainWindow();
    8.             ventana.IsEnabled = false;
    9.             this.Background = Brushes.LightGray;
    10.             Dialogo.IsOpen = true;
    11.         }

    image

     

     

    Como podemos observar hemos desactivado los elementos de la interfaz de usuario que están en segundo plano. Además cambiamos el fondo de estos elemento a gris para mejorar la experiencia de usuario. Por último abrimos el objeto PopUp.

    El siguiente paso es incluir el código Behind de los botones del PopUp. Comenzamos con el botón Aceptar:

    1.  
    2. private void Aceptar_Click(object sender, RoutedEventArgs e)
    3. {
    4.     Mensaje.Text = "Bienvenido " + txtNombre.Text;
    5.     this.Background = null;
    6.     HabilitarUI();
    7. }
    8. private void HabilitarUI()
    9. {
    10.     MainWindow ventana = new MainWindow();
    11.     ventana.IsEnabled = true;
    12.     Dialogo.IsOpen = false;
    13. }

    image           image  

    Como podemos observar mostraremos en la página principal un mensaje con el nombre de la persona logueada. Además eliminamos el fondo de la misma para que el usuario se entere que se ha logueado (aquí dejen su imaginación volar). Por último cerramos el PopUP y habilitamos la ventana.

    En el evento del botón cancelar  introducimos el siguiente código:

    1. private void Cancelar_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             HabilitarUI();
    4.             this.Background = Brushes.White;
    5.         }

    Como podemos observar realizamos similares acciones que en el anterior evento para dejar la interfaz de usuario como estaba por defecto.

     

     

     

     

    En Silverlight realmente es mucho más sencillo que en WPF, a nuestro proyecto tenemos que añadir un nuevo elemento, eligiendo como plantilla ChildWindow como podemos observar a continuación:

    image

    Ahora nos encargaremos de añadir las propiedades de la ventana (tamaño, fondo, etc) y los elemento que estarán incluidos en la misma. Para que la ventana aparezca y el resto de la interfaz de usuario este deshabilitada, simplemente tenemos que llamar al método Show desde el nombre del objeto que hace referencia a la ventana emergente como podemos observar a continuación:

    nuevoelemento.Show();

    La conclusión es que aunque no tengamos la funcionalidad nombrada, podemos utilizar diversos caminos para ofrecer al usuario una mejor experiencia de usuario en la que se centre en lo que realmente es importante en cada momento.

    Podeis descargar el ejemplo del artículo aquí

    Posted: 2/9/2010 12:16 por RAÚL MAYO | con 2 comment(s)
    Archivado en: ,
    Geolocalizando Tweets de Silverlight a través de Bing Maps

    Desde hace unos meses, a veces con aciertos otras con fallos, Twitter permite la geolocalización de todas las actualizaciones de estado(Tweets). Aprovechando esta función y utilizando las Funciones de Bing Maps y Silverlight. Voy  a crear un Iframe, dicho elemento podemos añadirlo como complemento de nuestra web (este es mi caso). Dicho complemento lo que nos va mostrar son las diferentes entradas catalogadas como #Silverlight en Twitter. Pero además un mapa con la ubicación de cada una de ellas, pudiendo acceder a ellas, bien a través del mapa o del texto con la correspondiente entrada.

    En primer lugar accedemos a Bing Maps, presionamos sobre el botón Map APPS:

    image

    Para más tarde seleccionar que tipo de localizadores queremos que muestre Bing Maps, en este caso los de Twitter:

     

    image

    De inmediato aparecerá la ubicación en la que nos encontramos y los diferentes Twitters que se han realizado.

    image

    Como deseamos filtrar los diferentes Twitters que se han enviado, accedemos a la pestaña de búsqueda y en el campo Keywords introducimos Silverlight.  El resto de  campos, podemos rellenarlos a nuestro antojo, para afinar más aún las diferentes búsquedas de los Tweets.

    image

    Al presionar sobre el botón Buscar, podemos observar si hay Tweets en esa zona. Para ampliar el número de Tweet simplemente ampliamos el campo de visión del mapa(realizando Zoom) . Esta acción conllevará que los diferentes parámetros del Iframe cambiarán.

    Ahora presionamos sobre embeber en tu sitio, de esta forma se generará el código necesario para añadir  posteriormente el complemento a tu web.

    image

    Como podemos observar tenemos una vista previa del elemento que vamos añadir a nuestra web, además del correspondiente código, que seleccionaremos, copiaremos e incluiremos en la web. De este modo podemos estar actualizados en todo momento de los Tweets de Silverlight que se generan en cualquier parte del mundo de una forma visual.

    Dinamizando la Geocodificación de Bing Maps en un proyecto Silverlight

    Dentro de los talleres orientados a aplicaciones de negocio de la plataforma Silverlight, que en próximas fechas desarrollaré en el Centro de Excelencia Software Microsoft, he tenido que trabajar con la Geocodificación que Bing Maps pone a nuestra disposición a través de una serie de servicio.

    Pero que significa esta palabra tan rimbombante (Geocodificación), pues es el proceso de asignar coordenadas geográficas (e.g. latitud-longitud) a puntos del mapa (direcciones, puntos de interés, etc.). Las coordenadas geográficas producidas pueden luego ser usadas para localizar el punto del mapa en un Sistema de Información Geográfica. Para que nos entendamos, en el ejemplo que vamos a desarrollar en este artículo, el usuario final va a introducir una dirección, reflejando dicha dirección en un objeto Mapa (que nos ofrece el  SDK de Bing Maps para Silverlight).El usuario final podrá interactuar con dicho elemento a través de la plataforma Silverlight.

    Para este artículo vamos a usar Silverlight 4 y Bing Maps Silverlight Control SDK, podéis descargarlos en los correspondientes enlaces. También tenemos que crear una cuenta Bing Maps para poder disfrutar de las diferentes características que nos ofrece esta plataforma. Para ello accedemos aquí, para crear una nueva cuenta.

    Hacemos clic sobre Crear en la sección Nuevo Usuario.

    image

    Al realizar esta acción nos pedirá la autentificación mediante Windows Live ID. Una vez introducidos los credenciales, pasaremos a rellenar los datos de la cuenta.

    image

    Seguidamente vamos a presionar sobre Create or View Keys, de este modo crearemos una clave que asociaremos en nuestro proyecto. Rellenamos los campos(Nombre de la aplicación, Url de la aplicación y tipo de aplicación) como podemos ver en la siguiente imagen:

    image

    Al presionar en Create Key se ha generado una nueva clave que hemos de introducirla en nuestro desarrollo:

    image

    Una vez realizada dicha acción, vamos a desarrollar nuestro proyecto en Silverlight, más adelante utilizaremos la citada clave.

    Abrimos Visual Studio 2010, para crear una nueva aplicación Silverlight que llamaremos PuntosInteresSL, como podemos observar en la siguiente imagen:

    image

    Por otro lado marcaremos que queremos alojar nuestra aplicación Silverlight en un sitio web y elegiremos la versión 4 de Silverlight para el proyecto que nos ocupa.

    image

    Añadimos las bibliotecas de Bing Maps que necesitamos para desarrollar las diferentes funcionalidades de ambas plataformas. Para ellos nos situamos sobre la carpeta Referencias, hacemos clic con el botón derecho del ratón y elegimos Añadir Referencia. Seleccionamos la pestaña Buscar y en la siguiente ruta C:\Program Files\Bing Maps Silverlight Control\V1\Libraries, seleccionamos las siguientes bibliotecas:

    image

    El siguiente paso es añadir el servicio de Bing Maps que nos va permitir la Geocodificación. Nos situamos nuevamente sobre la carpeta Referencias, hacemos clic con el botón derecho sobre la misma y elegimos Agregar referencia de servicio. En la ventana emergente que nos aparece al realizar la anterior acción, debemos introducir en el campo Dirección, la url del servicio (http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc). Presionamos sobre el botón Go para comprobar que la comunicación con el servicio se realiza de forma correcta. El servicio lo identificaremos con el nombre GeocodeService que debemos introducirlo en el apartado NameSpace:

    image

    Presionamos en OK y ya tenemos preparado el servicio para su posterior utilización.

    El siguiente paso es introducir la clave de la cuenta Bing Maps creada con anterioridad en App.xaml, de este modo utilizaremos dicho elemento como un recurso, sin necesidad de introducir en todo momento la clave.

    Una vez situados en App.xaml, dentro de la etiqueta <Application.Resources> introducimos <sys:String x:Key="MisCredenciales">Clave Cuenta Bing Maps</sys:String> siendo el resultado final de dicho archivo el siguiente:

    Credenciales
    1. <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    2.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    3.              xmlns:sys="clr-namespace:System;assembly=mscorlib"
    4.              x:Class="PuntosInteresSL.App"
    5.              >
    6.     <Application.Resources>
    7.         <sys:String x:Key="MisCredenciales">Clave Cuenta Bing Maps</sys:String>
    8.     </Application.Resources>
    9. </Application>

     

    Ahora vamos a centrarnos en la creación de la interfaz de usuario, para ello abrimos MainPage.xaml, el primer paso es referenciar las librerías de Bing Maps. Para ello dentro de la etiqueta <UserControl> introducimos xmlns:map="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl".

    Seguidamente, vamos a definir la estructura de los diferentes objetos que incluiremos dentro de la misma, para ellos añadimos el siguiente fragmento de código:

    1. <Grid x:Name="LayoutRoot" Background="White">
    2.         <Grid.ColumnDefinitions>
    3.             <ColumnDefinition Width="271*"/>
    4.             <ColumnDefinition Width="100*"/>
    5.         </Grid.ColumnDefinitions>
    6.         <Grid.RowDefinitions>
    7.             <RowDefinition Height="255*"/>
    8.             <RowDefinition Height="45*"/>
    9.         </Grid.RowDefinitions>
    10.     </Grid>

    Ahora vamos a introducir el objeto Mapa que hemos referenciado con anterioridad. En dicho objeto vamos a trabajar con las propiedades Center que muestra la latitud y longitud inicial del mapa. La propiedad ZoomLevel ofrece el nivel de ampliación del mapa en su estado original. Por último la propiedad Mode que es la vista que deseamos mostrar en el objeto Mapa.

    1. <map:Map x:Name="mapa" Center="40.225,-1.794" ZoomLevel="6" Mode="Road" Grid.Row="0" Grid.ColumnSpan="2"/>

    Ejecutamos la aplicación y podemos ver como aparece un mensaje sobre el mapa, en el que nos informa que no podemos utilizar dicho elemento por tener credenciales inválidos.

    image

    Ante este requisito, debemos utilizar el recurso que hemos creado con anterioridad del siguiente modo:

    1. <map:Map x:Name="mapa" Center="40.225,-1.794" ZoomLevel="6" Mode="Road" Grid.Row="0" Grid.ColumnSpan="2">
    2.             <map:Map.CredentialsProvider>
    3.                 <map:ApplicationIdCredentialsProvider ApplicationId="{StaticResource MisCredenciales}"/>
    4.             </map:Map.CredentialsProvider>
    5.         </map:Map>

    Ejecutamos y vemos como ahora podemos utilizar el mapa sin ningún tipo de problema.Por último en la interfaz de usuario vamos a introducir los dos últimos elemento. Por un lado introducimos un objeto TextBox que recogerá el punto de interés que desea el usuario introducir en el mapa. Por otro un botón que será el disparador de las diferentes acciones que permitan introducir en el mapa ese punto de interés.

    1. <TextBox x:Name="txbPI" Grid.Row="1" Grid.Column="0" Margin="10"/>
    2.         <Button x:Name="btnGeocode" Content="Punto de Interés" Grid.Row="1" Grid.Column="1" Margin="5" Click="btnGeocode_Click"/>

    Ahora nos vamos a situar en MainPage.xaml.cs, seguidamente nos desplazaremos hasta el evento clic generado con anterioridad para el botón. Primeramente referenciamos las librerías:

    1. using Microsoft.Maps.MapControl;

      Dentro de dicho evento introducimos el siguiente fragmento de código:

     

    1. private void btnGeocode_Click(object sender, RoutedEventArgs e)
    2.         {
    3.             GeocodeService.GeocodeServiceClient geocodeClient = new GeocodeService.GeocodeServiceClient
    4.  
    5.            ("CustomBinding_IGeocodeService");
    6.  
    7.             GeocodeService.GeocodeRequest resquest = new GeocodeService.GeocodeRequest();
    8.             resquest.Query = txbPI.Text;
    9.             resquest.Credentials = new Microsoft.Maps.MapControl.Credentials();
    10.             resquest.Credentials.ApplicationId = App.Current.Resources["MisCredenciales"] as string;
    11.  
    12.             geocodeClient.GeocodeCompleted += new EventHandler<GeocodeService.GeocodeCompletedEventArgs>(geocodeClient_GeocodeCompleted);
    13.             geocodeClient.GeocodeAsync(resquest);
    14.         }

     

    Como podemos observar creamos un objeto GeocodeServiceClient, que nos permite comunicar la aplicación con el servicio GeocodeService. Dicho servicio requiere del Objeto GeocodeRequest que envía la petición de un nuevo punto de interés a través del texto introducido en el TextBox. Pero este acceso al servicio no sería posible si no enviaríamos los credenciales de la cuenta Bing Maps. Por último la petición al servicio se ha de realizar de forma asincrona, cuando la petición regresa la controlamos a través del controlador de eventos geocodeClient_GeocodeCompleted.

    Ahora vamos a introducir el evento citado con anterioridad. En el obtenemos un array con una serie de coincidencias con el texto introducido en el TextBox. Como solo nos interesa el primer elemento, a través de LINQ obtenemos ese primer elemento.Tomamos la longitud y latitud de ese elemento y creamos en la interfaz de usuario un nuevo localizados(Punto de Interés). El último paso es ofrecer la mejor vista de ese punto de interés por lo que el objeto mapa realizará un Zoom sobre dicho punto de interés a fin de mejorar la experiencia de usuario.

    1. private void geocodeClient_GeocodeCompleted(object sender, GeocodeService.GeocodeCompletedEventArgs e)
    2.         {
    3.             GeocodeService.GeocodeResponse response = e.Result;
    4.             if (response.Results.Count > 0)
    5.             {
    6.                 GeocodeService.GeocodeResult result = response.Results.First();
    7.                 if (result.Locations.Count > 0)
    8.                 {
    9.                     Pushpin pushpin = new Pushpin();
    10.                     Location location = new Location(result.Locations.First().Latitude, result.Locations.First().Longitude);
    11.                     pushpin.Location = location;
    12.                     mapa.Children.Add(pushpin);
    13.                     mapa.SetView(result.BestView);
    14.                   
    15.                     
    16.                 }
    17.             }
    18.  
    19.         }

    Ejecutamos la aplicación e introducimos en el TextBox Niagara Falls y podemos ver el siguiente resultado:

    image

    En definitiva, podemos obtener un mayor rendimiento de las dos plataformas al utilizar todas las capacidades de una forma dinámica, ayudando con ello a la mejora de la experiencia de usuario, además de ofrecer al mismo aplicaciones útiles.

    Podéis descargar el proyecto completo aquí

    Más artículos Página siguiente >