Jorge Serrano - MVP Visual Developer - Visual Basic

Introducción

Desde hace poco tiempo, tengo entre mis manos un dispositivo de Microsoft especialmente diseñado para Xbox 360, y el cual me permite conectarlo a mi consola y poder chatear entre otras cosas.

Lo más interesante de este dispositivo, es que tiene un modo de selección dual: Xbox 360 y Bluetooth.

Según rezan los datos de Microsoft, el modo de selección Bluetooth, nos permite conectarlo con dispositivos móviles y PCs, así que me he puesto a trastear con él y efectivamente, es o puede llegar a ser un buen aliado.

Características

Entre sus características y pruebas que he hecho, destaco las siguientes:

Conexión dual: Xbox 360 y conexión Bluetooth.

Conectividad: Xbox 360, PCs, otros dispositivos.

Soportes Bluetooth: HSP, HFP y A2DP.

Carga a través de microUSB-USB, conectándolo al PC, Xbox 360 u otra fuente de alimentación.

Más datos.

Pruebas

Pero para ver su funcionamiento, que mejor que probarlo digo yo…

Así que me he puesto manos a la obra y he probado el Xbox 360 Wireless Headset en varios dispositivos.

Xbox 360: Obviamente, no tengo apenas nada que decir. Que funciona tal y como se espera.

Windows Phone: He usado este terminal telefónico porque es el que tengo ahora mismo. Seguramente funcione con todos,… al menos, todos los que soporten los protocolos de comunicación Bluetooth HSP, HFP o A2DP. En mi caso he usado un modelo Nokia Lumia 800, y la conexión entre ambos dispositivos ha sido satisfactorio. He podido escuchar música sin problemas, aunque también funciona para recibir llamadas o mantener conversaciones con Skype por ejemplo.

iPad: También me he puesto a juguetear con mi iPad 3, y al igual que con mi Windows Phone, el funcionamiento ha sido el esperado, pudiendo escuchar a través del Xbox 360 Wireless Headset lo que proyectaba en mi iPad.

PC: De igual forma, este dispositivo se ha conectado satisfactoriamente a mi ordenador.

Precio

El precio oscila según donde lo compremos, pero éste puede variar entre los 23€ y los 50€.

Mi consejo a día de hoy, cuando estoy publicando esta entrada, es adquirirlo en Amazon por 23€.

Conclusiones

Lo considero un dispositivo muy útil y a bajo precio (pensando como bajo precio el mínimo posible), capaz de conectarse a diferentes dispositivos, permitiéndonos escuchar música, mantener conversaciones de chat o de Internet como por ejemplo Skype o Lync, y pudiendo sacarle provecho de diferentes formas.

Es uno de esos dispositivos que sin ser imprescindible, lo considero muy útil y recomendado.

Actualización

He continuado probando este dispositivo y en concreto, con una PSP Go. Puedo decir con seguridad, que el dispositivo se enlaza con la consola portátil de Sony, y que permite escuchar el sonido de los juegos por este dispositivo... así que ya tiene otro uso más. :)

Publicado por Jorge Serrano | con no comments
Archivado en:

Foto: Jim Norton

Introducción

Estaba revisando mis Twitts en Twitter cuando me encuentro con un mensaje que me lleva a un artículo en la página web consultoras.org y de título "Mejor el Open Source conocido, que un cloud inmaduro" y que en realidad, nos lleva a la fuente original del artículo en siliconnews.com y a su autora, Nerea Bilbao.

Centrándome en el artículo original, éste trata acerca de un estudio mandado hacer por Amadeus a un prestigioso académico IT en el que en rasgos generales concluye, que el cloud está inmaduro y se debería mirar más hacia soluciones Open Source.

Te invito a leer previamente este artículo y posteriormente si quieres, leer mis comentarios al respecto, ya que me gustaría puntualizar algunas cosas.


Algunos detalles del artículo

Antes de hacer mis apreciaciones sobre el estudio, desgranaré algunas partes principales del mismo.

En dicho estudio, el "prestigioso" académico IT (Jim Norton) asevera y urge a los CIOs de las empresas de IT, que deberían considerar seriamente las soluciones y productos de código abierto (open source) sobre el Software propietario o los servicios públicos de tipo cloud.

Para ser justos con las aseveraciones de dicho estudio, en él, se indica que lo primero es el open source, no el cloud.

Y concluye con que la nube pública (public cloud) es un negocio inmaduro.

Y aquí viene quizás lo mejor, cuando Norton afirma que espera que hagamos un mayor ahorro de costes mediante el uso de open source sin la necesidad de utilizar una solución basada en la nube.

No pongo en duda la rigurosidad del estudio, pero permitidme que haga una pequeña salvedad que sembrará la duda y que me ha hecho meditar el no escribir este post de entrada, y es el hecho de que Amadeus esté detrás del estudio, ya que Amadeus se caracteriza por apoyar el Open Source, así que dudo mucho que haga un estudio que les diga que lo interesante es el Software propietario y el cloud, pero vamos... eso no quita para que haga algunas matizaciones al respecto de dicho estudio.

Pero pongamos los puntos sobre las íes y obviemos quién ha hecho el estudio, sino, analicemos las conclusiones... que para mi parecer son alarmantes, ya que si algún CIO lee esto y se lo traga a pies juntillas, quizás se encuentre en poco tiempo con problemas por haber adoptado o una mala solución a sus problemas, o una dirección errónea para su empresa.

Pero vayamos por partes y poco a poco.


Algunas puntualizaciones al respecto

No voy a empezar ahora a contar si el open source es bueno o es malo. Más que nada, porque yo también he hecho open source y yo también he consumido open source, pero hablemos de algo más concreto. Los problemas y las soluciones.

Ni todos los problemas se resuelven con open source, ni la solución a todos los problemas es el open source.

Según este estudio, el open source resuelve los problemas de los costes, y pone en el disparadero una palabra... el miedo.

Para ello, se nutre de una afirmación que es una falacia, por muy prestigioso que sea el señor Norton, y es el hecho de afirmar que la nube es inmadura.

Hagamos un pequeño flashback y viajemos a principios del siglo XXI, 2002, 2003 aproximadamente... ¡FlAsH!.

...

Ya estamos en el años 2002, 2003 y os voy a hablar de ASP, pero como el término ASP en informática puede dar a confusión, seré más concreto y hablaré de Application Service Provider.

El CLOUD o el embrión del mismo no es nuevo señores. Yo precisamente estuve a punto de entrar en una compañía en el año 2003 que se iba a dedicar a algo parecido a lo que hoy se conoce como cloud,... bueno, era en realidad algo casi igual, pero por aquel entonces, sí estaba inmaduro (doy fe).

El problema es que en esos años, el Software que se podía ejecutar en la nube era prácticamente nulo, es decir... no había apenas Software que funcionara como Servicio (SaaS).

Sin embargo hoy, todo eso ha cambiado porque la tecnología se ha ido adaptando y mejorando, y el desarrollo del Software también.

 

¿Está maduro el Cloud?

Aquí me gustaría preguntarle al señor Norton que entiende él por madurez, ya que afirmar que "algo" está maduro o no es muy complicado, y si hablamos de tecnologías más aún, sobre todo porque las tecnologías no son estáticas, evolucionan, cambian, mutan, etc. Y él mejor que nadie, debería saber que lo mismo le ocurre al open source,... ¿alguien recuerda la palabra mantenimiento y sabe lo que realmente significa?, ¿alguien recuerda la palabra o frase de flexibilidad y rapidez al cambio?.

Pero ojo... las afirmaciones del señor Norton en dicho estudio son aún más dolorosas, ya que no habla de inmadurez como tal, sino de "negocio inmaduro".

Y yo me pregunto en ese caso... ¿qué hay que hacer?, ¿esperar a que salga una solución open source de tipo cloud?.

El problema es que no sé si realmente el señor Norton conoce lo que es el cloud, y me explico.


El cloud de Microsoft

Pongo y hablo del cloud de Microsoft porque es el que más conozco, así que permitidme que hable de él para exponer porqué el señor Norton se está columpiando como un colegial (cosa que me sorprende debido a su prestigio que asocio a su experiencia).

El cloud de Microsoft por ejemplo, permite instalar tanto Software propietario como open source.

Sin embargo, hay algo que permite el cloud y que no permite el Software de tipo open source (NI EL PROPIETARIO) y es la redimensión de los sistemas en base al consumo, al crecimiento, etc., así como otras características ASOCIADAS al HARDWARE. Eso sin contar con el ahorro de costes por el mantenimiento de los sistemas o por la actualización de las aplicaciones base ejecutándose en ellos.

Y es que una parte de dicho estudio que ha sido obviada interesadamente creo yo, es el hecho de separar el SOFTWARE del HARDWARE.

Pero dudo enormemente que el señor Norton lo haya obviado desinteresadamente, y que haya ignorado el hecho de que el Cloud, no sólo es SOFTWARE, también es HARDWARE, pero queda muy bien desviar la atención, hacer un estudio tendencioso y decir las verdades a medias, para posteriormente, que el incauto empresario se lo trague y contrate a Amadeus o al señor Norton para que les cobre nosecuantos dólares en consultoría antes de que el maligno Software propietario o el cloud lo haga antes que ellos.

Pero pensemos las cosas con mayor profundidad...

Si una empresa adquiere Software open source, ¿dónde lo va a ejecutar?. En un Hardware por el que habrá pagado unos cuantos cientos de dólares supongo.

Si una empresa adquiere Software propietario, ¿dónde lo va a ejecutar?. En un Hardware por el que habrá pagado unos cuantos cientos de dólares supongo.

Es decir, ambos van a tener que pagar unos cientos de dólares por el Hardware, con la salvedad del Software que en el caso del open source es gratis "por defecto" y de pago en el propietario.

Sin embargo, para el open source, muchos tendrán que adquirir los correspondientes contratos de soporte pagando al final unos cuantos dólares también.

¿Acaso el open source al que todos asocian erróneamente con gratis sale más barato que el propietario?. Pues depende de cada problemática a resolver, pero recordad una cosa que a mí siempre me decían de pequeñito y que me aprendí a fuego… “nadie da duros a pesetas”.

Sea como sea, en ambos casos también (open source o propietario), necesitarán un departamento de sistemas (externalizado o interno) que se encargue de mantener dicho Software y dicho Hardware. Un grupo de personas que se encargue de dar soporte, que aporte valor y que asegure el buen funcionamiento del sistema y que los usuarios no tengan problemas de acceso, seguridad, etc. Y que ante la posibilidad de que se den fallos en el sistema los resuelva fácil y rápidamente, y que incluso si la demanda de usuarios crece o decrece, sea fácil y rápidamente escalable en las dos direcciones (hacia adelante o hacia atrás si la demanda baja por ejemplo), y todo sin incidir directamente en los costes.

No es de recibo por ejemplo, que adquiramos dos máquinas nuevas para soportar un crecimiento de usuarios y que pasado un año, la empresa se dé de baja del servicio por ejemplo, y nos comamos con patatas las dos máquinas o las revendamos como podamos para no tirar el dinero invertido por el retrete… ¿a alguien le suena¿. Si algún CIO lo lee, seguro que sí, yo al menos sin serlo hoy, recuerdo algún que otro caso parecido.


¿Y qué aporta el Software open source?

Seamos serios y rigurosos en las cosas en las que tenemos que serlas.

A mí, lo que me parece realmente sangrande de este estudio, es mezclar intencionadamente churras con merinas y hacer creer a los CIOs que el open source es la solución a todos sus problemas, que el Software propietario es el origen de sus problemas, y que el cloud es "algo" que está ahí pero que no no va a resolver sus problemas de IT debido a que es inmaduro.

Personalmente creo, que esas aseveraciones tienen un único fundamento... "amigo CIO, sigue gastándote la pasta en el open source y pasa del Software propietario". El tema es que el cloud no es un problema de Software open source vs propietario, va más allá, pero es mejor enredar el asunto y hacer creer que digo blanco cuando en realidad quería decir negro. Como dije en Twitter al respecto, es mejor mezclar churras con merinas y aseverar inconscientemente que ha salido una cabra, para afirmar a continuación que todas las ovejas son cabras. Si alguien se lo quiere tragar, adelante.

Si eres CIO y has leído esto, sólo te deseo una buena elección en la solución de la problemática y no dejarte llevar por estudios tendenciosos, pero para concluir, pondré ejemplos reales de muchas empresas (ni una ni dos) que trabajando hoy con el sistema inmaduro de la nube o cloud, se han evitado mil y un problemas, han ahorrado mucho dinero, han escalado sus sistemas de forma eficiente y rápida, han podido hacer frente a retos de forma mucho más rápida a como lo hacían en el pasado (imaginemos lo que ha pasado con la transmisión REAL de los Juegos Olímpicos de Londres en la nube), y han podido hacer un seguimiento de costes mucho más preciso.

Para ser la nube o cloud inmaduro no está nada mal ¿verdad?.

Este tipo de estudios, lejos de empequeñecer al cloud, le hace aún si cabe más grande.

¿Para cuando el próximo estudio señor Norton?.

Publicado por Jorge Serrano | 2 comment(s)
Archivado en:

No suelo poner este tipo de noticias en mi blog de forma pública (más bien, creo que es la primera vez que lo hago en Internet), pero en este caso voy a hacer una excepción porque creo que la ocasión lo merece.

He decidido cambiar de aires y cambiar de empresa.

He decidido dejar mi actual empresa, Sogeti (grupo Cap Gemini y partner de Microsoft), y apostar por una empresa en auge (Partner de Microsoft también), con gente implicada y fantástica profesional y personalmente, y envuelta en proyectos y retos nacionales e internacionales interesantísimos, y un excepcional futuro por delante.

Durante este último año y medio he estado inmerso en un interesantísimo proyecto en un cliente sensacional. De la nada y de forma colaborativa hemos empezado a dar forma a un producto enorme introduciendo en el mismo multitud de tecnologías nuevas para el cliente, y cubriendo las necesidades iniciales que debían ser abordadas para conseguir que el proyecto resultara un éxito. Al ser un proyecto empresarial bastante grande y complejo, aún le falta recorrido, pero la parte fundamental sobre la que se ha estado trabajando en todo este tiempo ha sido llevada a cabo con éxito.

Entre otros cambios, se ha impulsado el paso de PowerBuilder, Source Safe, VB6, C++, Oracle y Java a nuevas tecnologías como TFS, metodologías Scrum, UML, C#, Oracle y SQL Server (entre otras cosas), todo ello bañado de OOP puro, patrones, buenas prácticas, guías de arquitectura y desarrollo.

Y para colmo, todo ello adornado de un buen compañerismo y buena gente.

En resumen,... no tengo nada más que buenas palabras y agradecimientos para mi anterior empresa y los compañeros que he tenido tanto en Sogeti como en el cliente en el que he estado trabajando durante todo este tiempo.

Sin embargo, cuando uno menos se lo espera, aparecen oportunidades profesionales que a uno le tientan y le hacen dudar de si debe cambiar su camino profesional o no. Eso es lo que me ha pasado en esta ocasión, y de verdad que me siento muy afortunado por ello y tremendamente agradecido a mi nueva empresa el hecho de que hayan pensado en mí.

Lamentablemente, he cambiado demasiadas veces de empresa en los últimos años, algo que desde luego no me agrada reconocerlo pero que tampoco nadie tiene porqué pensar mal de ello ni tampoco tengo porqué ocultarlo porque no ha sido por nada extraño. A veces, los cambios han sido motivados por temas personales/profesionales, y en otras ocasiones (las menos por suerte) porque el mercado tan voraz e inesperado en el que estamos todos inmersos, me ha “invitado” a llevar a cabo en alguna ocasión un cambio de aires (lo que algunos llaman “ajustes”).

El caso, y lo que más me importa ahora mismo, es que no todos los días te presentan delante de tus ojos un caramelo… una oportunidad fantástica de formar parte de un proyecto de largo recorrido, de grandes expectativas y de un futuro que a simple vista parece no tener límites. En esos casos, de los que la experiencia me ha hecho saber que no ocurren todos los días, es muy difícil negarse a dar el paso definitivo.

Si además de todo eso, vas a tener compañeros de trabajo fantásticos y como la copa de un pino (que diría un famoso periodista deportivo), las decisiones son si cabe aún más fáciles de tomar.

Cierto es que la situación económica y social actual le manda a uno ser quizás más conservador, pero no es menos cierto que las barreras están para romperlas y los retos para vencerlos, así que me he decidido a dar ese paso hacia adelante y agarrar con las dos manos la oportunidad que se me ha presentado.

Espero estar a la altura de las circunstancias.

Así que a partir de ahora, formo parte de la familia Spenta dentro de la cuál, hay personas que algunos ya conocéis en los blogs de Geeks como David Martos o Luis Ruiz Pavón, y otras que sin tener un blog tan seguido o conocido, son extraordinarios profesionales y seguro que más de uno se hará notar dentro de poco.

Spenta, There we go!

Publicado por Jorge Serrano | 6 comment(s)
Archivado en:

Utilizando Segoe UI Symbol

 

Utilizando Segoe UI Symbol (I)

Introducción

Cuando hablaba en una entrada posterior de la barra de aplicación, hablaba de la fuente de letra Segoe UI Symbol de Windows 8.

Aunque esta fuente de letra se incorporó en Windows 7, es en Windows 8 cuando ha logrado obtener mayor relevancia e importancia, sobre todo para nuestras aplicaciones Metro.

En esta entrada vamos a resolver la posible duda que puede surgirnos acerca de visualizar cada uno de los caracteres especiales que podemos encontrar en esta fuente de letra y que podemos utilizar en nuestras aplicaciones.

Acceder a los símbolos

Lo primero que debemos hacer es acceder a los símbolos.

Para ello, abriremos el Panel de Control y accederemos a Fuentes.

Dentro de las fuentes de letra, pulsaremos la opción Buscar un carácter del panel de la izquierda.

Dentro de esta ventana, accederemos a la fuente de letra Segoe UI Smbol.

Ahora sólo nos quedará saber cómo extraer el código de un carácter especial.

Si nos movemos por la barra de scroll de esta ventana, observaremos más o menos de la mitad hacia abajo, que empiezan a aparecer caracteres especiales.

Bastará con hacer clic sobre uno de ellos para obtener el código de ese carácter y fijarnos en el código que nos indica la ventana Mapa de caracteres.

Una vez que hemos anotado el código del carácter que queremos utilizar, tan sólo nos queda utilizarlo en nuestra aplicación.

Utilizando el símbolo del carácter obtenido

Iniciaremos una nueva aplicación Metro de nombre Sample5 y dentro de la página principal de la aplicación insertaremos un control TextBlock.

El código XAML asociado quedará de la siguiente manera:

   1: <TextBlock Margin="200,200,0,0" FontFamily="Segoe UI Symbol" FontSize="124" Text="&#x23F0;" />

Si lo queremos, podemos obviar el nombre de la fuente, ya que en Metro y por defecto, la fuente de letra utilizada es Segoe UI Symbol.

Por lo tanto, podemos dejar nuestro código XAML de la siguiente manera:

   1: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
   2:         <Canvas>
   3:             <TextBlock Margin="200,200,0,0" FontSize="124" Text="&#x23F0;" />
   4:         </Canvas>
   5: </Grid>

Nuestra aplicación quedará por lo tanto de la siguiente manera:

Cabe destacar, que esta fuente de letra contiene más de 1000 códigos diferentes de iconos que podremos utilizar en nuestras aplicaciones Metro, de ahí la importancia de comentar esto y de escribir esta entrada. Para que sepamos y conozcamos las herramientas que tenemos a nuestro alcance y los recursos que a veces nos pueden ahorrar mucho tiempo.

Barras de botones o barras de aplicación

Parte I

 

Barras de botones o barras de aplicación (II)

Estilos a usar en los controles de la barra de aplicación

Los estilos utilizados en este ejemplo corresponden con los estilos que Microsoft nos ofrece y que nos simplifica el trabajo.

Situándonos en el Explorador de Soluciones y en nuestro proyecto Sample4, encontraremos dentro de la carpeta Common un fichero de nombre StandardStyles.xaml.

Este fichero contiene los estilos con los que podemos trabajar.

Si observamos el código XAML, veremos que por ejemplo para el control Button denominado Editar, utilizamos un estilo EditAppBarButtonStyle.

Como digo, este estilo no lo hemos creado, y hemos utilizado uno que Microsoft nos ha dado y que encontramos en el fichero de estilos mencionado anteriormente, StandardStyles.xaml.

   1: <Style x:Key="EditAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
   2:         <Setter Property="AutomationProperties.AutomationId" Value="EditAppBarButton"/>
   3:         <Setter Property="AutomationProperties.Name" Value="Edit"/>
   4:         <Setter Property="Content" Value="&#xE104;"/>
   5: </Style>

Si nos fijamos bien en este código XAML, éste estilo utiliza a su vez el estilo AppBarButtonStyle que es un estilo genérico de comportamiento de un botón en la barra de botones de la aplicación.

Aquí también, encontramos algo que nos puede interesar.

Es la propiedad AutomationProperties.Name y que por defecto, tiene un valor Value a Edit.

También tenemos otra propiedad no menos interesante, de nombre Content y que tiene valor Value a &#xE104;.

Si quisiéramos cambiar el valor concreto para un idioma y otro distinto para otro idioma, deberíamos empezar a jugar con la localización de nuestra aplicación en Content.

Nota: Ver las entradas sobre localización que tratan la internacionalización de nuestras aplicaciones.

Es interesante ver que la propiedad Content corresponde con un código de escritura, ya que se utiliza una fuente de letra que encontraremos en el estilo AppBarButtonStyle.

Es el Setter siguiente:

   1: <Setter Property="FontFamily" Value="Segoe UI Symbol"/>

Y es que en Metro, podemos hacer uso de la fuente de letra Segoe UI Symbol.

Una fuente de letra Metro con códigos que corresponden con iconos ya prediseñados para ser utilizados en nuestras aplicaciones.

Un ejemplo de uso de esta fuente de letra y un código de la misma sería:

   1: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
   2:         <Canvas>
   3:             <TextBlock Margin="200,200,0,0" FontFamily="Segoe UI Symbol" 
   4:                        FontSize="20" Text="Fotos &#xE114;" />
   5:         </Canvas>
   6: </Grid>

He incluso si quisiéramos aprovechar lo que Microsoft nos ofrece, podríamos crear un botón fuera de la propia barra de botones rizando el rizo de la siguiente manera:

   1: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
   2:         <Canvas>
   3:             <Button Style="{StaticResource AppBarButtonStyle}"  
   4:                     Margin="200,200,0,0" FontFamily="Segoe UI Symbol" 
   5:                     FontSize="20" Content="&#xE114;" />            
   6:         </Canvas>
   7: </Grid>

No voy a descubrir ahora la bondad de los estilos, pero como podemos observar, podemos sacar mucho provecho de todo esto y en concreto de los estilos que encontraremos por defecto en el fichero StandardStyles.xaml.

Agregando eventos a un botón de la barra de aplicación

Como viene siendo habitual, la forma de agregar un evento a un botón de la barra de aplicación no difiere en nada con la forma estándar o habitual de hacerlo dentro del código XAML.

Imaginemos uno de los botones de la barra de aplicación. Bastará con indicarle el evento Click por ejemplo y asignarle el código del evento propiamente dicho.

   1: <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" 
   2:         Tag="Editar" Click="Edit_Click_1" />

Dentro del código del evento en C# para el caso de MainPage.xaml.cs, escribiremos las acciones correspondientes.

Agregando otros controles a la barra de aplicación

Ya comenté anteriormente, que en la barra de aplicación podíamos agregar los controles que consideráramos oportunos.

Imaginemos que de acuerdo a la barra de aplicación con la que hemos estado jugando, quisiéramos agregar un control TextBlock en el que mostrásemos la fecha y hora actual.

Podríamos insertar nuestro control en uno de los dos StackPanel que existen, pero vamos a crear un tercer StackPanel para que veamos como quedaría todo.

Nuestro control en código XAML quedaría de la siguiente manera:

   1: <TextBlock x:Name="FechaHora" Text="30/06/2012 11:56:12" FontSize="20" VerticalAlignment="Center" />

Y en nuestra barra de aplicación, los tres bloques o paneles StackPanel quedarían de la siguiente manera:

   1: <Page.BottomAppBar>
   2:         <AppBar x:Name="MenuOptionBottom" IsOpen="True" Opacity="0.75" IsSticky="False" 
   3:                 Background="#055565" VerticalAlignment="Bottom">
   4:             <Grid>
   5:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
   6:                     <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" Tag="Editar" />
   7:                     <Button x:Name="Refresh" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refrescar" />
   8:                     <Button x:Name="Save" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Guardar" />
   9:                 </StackPanel>
  10:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
  11:                     <TextBlock x:Name="FechaHora" Text="30/06/2012 11:56:12" FontSize="20" VerticalAlignment="Center" />
  12:                 </StackPanel>
  13:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
  14:                     <Button x:Name="Help" Style="{StaticResource HelpAppBarButtonStyle}" Tag="Ayuda" />
  15:                     <Button x:Name="Delete" Style="{StaticResource DeleteAppBarButtonStyle}" Tag="Eliminar" />
  16:                 </StackPanel>
  17:             </Grid>
  18:         </AppBar>
  19: </Page.BottomAppBar>

Nuestra aplicación en ejecución quedaría de la siguiente manera:

Barras de botones o barras de aplicación

Parte II

 

Barras de botones o barras de aplicación (I)

Introducción

El estilo Metro es muy particular.

Cuando digo muy particular me refiero a que Microsoft no nos recomienda salirnos de las guías de diseño establecidas para que una aplicación tenga ese aspecto.

Una de esas guías es la recomendación de usar barras de botones que tienen una determinada forma y que para facilitarnos la vida, ha incorporado Microsoft con un conjunto de iconos por defecto.

Todo lo que sea salirnos de esos márgenes, puede llevar con una posibilidad muy alta, a que nuestra aplicación no pase el corte de certificación.

Pero no nos preocupemos con esos detalles y veamos entonces como crear barras de botones con un aspecto Metro en nuestras aplicaciones.

Creación de nuestra aplicación

La primera acción que acometeremos es la de crear nuestra aplicación Metro.

En nuestro caso, iniciaremos Visual Studio 2012 y crearemos un aplicación como lo hemos venido haciendo en todas las entradas anteriores de esta pequeña guía.

Como nombre de nuestra aplicación, Sample4.

Nuestra aplicación en el Explorador de Soluciones quedará como se indica en la siguiente imagen:

Una vez hecho esto, vamos a ponernos manos a la obra.

Creación de la barra de aplicación

Para crear la barra de aplicación en nuestra página MainPage.xaml, vamos a acceder al código XAML de la misma.

Dentro del código XAML, vamos a centrarnos en una etiqueta Page que podemos variar en el caso de que queramos que nuestra barra de opciones aparezca en la parte superior de la página:

   1: <Page.TopAppBar>
   2: ...
   3: </Page.TopAppBar>

O en la parte inferior de la misma:

   1: <Page.BottomAppBar>
   2: ...
   3: </Page.BottomAppBar>

Dentro de estas etiquetas, prepararemos el menú de opciones de nuestra aplicación.

Dentro de la barra que vamos a crear, podemos insertar otros controles (una caja de texto, un botón,...) pero por defecto, Microsoft nos proporciona un conjunto de opciones que podemos reutilizar estableciendo un aspecto Metro de forma muy ágil.

Aún y así, aunque hayamos declarado la barra de botones superior o inferior a la página, todavía no hemos creado ninguna barra.

Para crear una barra de botones u opciones, vamos a utilizar la etiqueta AppBar:

   1: <AppBar>
   2:    <Grid>
   3:    ...
   4:    </Grid>
   5: </AppBar>

Y dentro de la etiqueta Grid, indicaremos cada uno de los botones o controles que queremos insertar dentro de la barra de botones.

Para hacerlo al revés, voy a mostrar en primer lugar lo que quiero lograr, y posteriormente como lo he hecho.

El aspecto de nuestra aplicación final es el que se muestra en la siguiente imagen:

El cómo lo he llevado a cabo, es creando dos barras de opciones para la página MainPage.xaml.

En el caso de la barra superior, el código XAML quedará de la siguiente manera:

   1: <Page.TopAppBar>
   2:         <AppBar x:Name="MenuOptionTop" IsOpen="True" Opacity="1" IsSticky="True" 
   3:                 Background="#055565" VerticalAlignment="Bottom">
   4:             <Grid>
   5:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
   6:                     <Button x:Name="Edit2" Style="{StaticResource EditAppBarButtonStyle}" Tag="Editar" />
   7:                     <Button x:Name="Refresh2" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refrescar" />
   8:                     <Button x:Name="Save2" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Guardar" />
   9:                 </StackPanel>
  10:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
  11:                     <Button x:Name="Help2" Style="{StaticResource HelpAppBarButtonStyle}" Tag="Ayuda" />
  12:                     <Button x:Name="Delete2" Style="{StaticResource DeleteAppBarButtonStyle}" Tag="Eliminar" />
  13:                 </StackPanel>
  14:             </Grid>
  15:         </AppBar>
  16: </Page.TopAppBar>

En el caso de la barra inferior, el código XAML quedará de una manera prácticamente idéntica:

   1: <Page.BottomAppBar>
   2:         <AppBar x:Name="MenuOptionBottom" IsOpen="True" Opacity="0.75" IsSticky="True" 
   3:                 Background="#055565" VerticalAlignment="Bottom">
   4:             <Grid>
   5:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
   6:                     <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" Tag="Editar" />
   7:                     <Button x:Name="Refresh" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refrescar" />
   8:                     <Button x:Name="Save" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Guardar" />
   9:                 </StackPanel>
  10:                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
  11:                     <Button x:Name="Help" Style="{StaticResource HelpAppBarButtonStyle}" Tag="Ayuda" />
  12:                     <Button x:Name="Delete" Style="{StaticResource DeleteAppBarButtonStyle}" Tag="Eliminar" />
  13:                 </StackPanel>
  14:             </Grid>
  15:         </AppBar>
  16: </Page.BottomAppBar>

Como son dos barras de botones prácticamente idénticas con la salvedad de que una se muestra en la parte superior de la página y otra en la inferior, vamos a centrarnos en una de ellas, por ejemplo, en la de la barra inferior de la página y que corresponde con la etiqueta Page.BottomAppBar.

Etiqueta AppBar

Si analizamos esta barra de opciones, comprobamos que dentro de esta etiqueta tal y como explicaba anteriormente, nos encontramos con una etiqueta AppBar.

A esta etiqueta la he dado algunas propiedades que considero interesantes a destacar.

En el código XAML lo identificamos con el siguiente código:

   1: <AppBar x:Name="MenuOptionBottom" IsOpen="True" Opacity="0.75" 
   2: IsSticky="False" Background="#055565" VerticalAlignment="Bottom">

La propiedad IsOpen nos indica si la barra de opciones debe estar abierta (visible) True o no False.

La propiedad Opacity nos indica la opacidad del fondo de la barra de botones. Esta propiedad vale 1 por defecto y su valor oscila de 0 a 1, siendo 1 el valor de opacidad más baja o nula, y 0 la de mayor opacidad o transparencia completa.

La propiedad IsSticky a False hará que nuestra barra se desvanezca cuando perdemos el foco.

La propiedad Background corresponde con el código de color de fondo de la barra, y la propiedad VerticalAlignment que he usado, me permite alinear verticalmente el contenido de la barra.

Botones de la barra de aplicación

Dentro de la etiqueta AppBar hemos creado una etiqueta Grid, y dentro de esta última, un par de etiquetas StackPanel.

El objetivo de cada bloque StackPanel es el de hacer que unos botones aparezcan en la parte izquierda de la barra, y otros en la parte derecha de la misma.

En el código XAML, nuestro código queda de la siguiente manera:

   1: <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
   2:                     <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" Tag="Editar" />
   3:                     <Button x:Name="Refresh" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refrescar" />
   4:                     <Button x:Name="Save" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Guardar" />
   5: </StackPanel>
   6: <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
   7:                     <Button x:Name="Help" Style="{StaticResource HelpAppBarButtonStyle}" Tag="Ayuda" />
   8:                     <Button x:Name="Delete" Style="{StaticResource DeleteAppBarButtonStyle}" Tag="Eliminar" />
   9: </StackPanel>

Como podemos apreciar, hemos creado dos bloques o paneles (StackPanel) dentro de nuestra barra de botones.

La propiedad Orientation nos permite indicar la orientación de nuestra barra de botones. En este caso, Horizontal.

De igual manera, aquí podemos alinear horizontalmente cada panel. De hecho, el primero de ellos lo hemos orientado a la izquierda y el segundo a la derecha.

Esto lo logramos con la propiedad HorizontalAlignment, dándole el valor que consideremos oportuno. Left o Right. Hay otros dos posibles valores Center o Stretch.

Igualmente, podríamos utilizar la propiedad VerticalAlignment que en este caso he obviado.

Finalmente y dentro de la cada StackPanel, he agregado los controles y botones que he considerado oportuno.

   1: <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
   2:                     <Button x:Name="Edit" Style="{StaticResource EditAppBarButtonStyle}" Tag="Editar" />
   3:                     <Button x:Name="Refresh" Style="{StaticResource RefreshAppBarButtonStyle}" Tag="Refrescar" />
   4:                     <Button x:Name="Save" Style="{StaticResource SaveAppBarButtonStyle}" Tag="Guardar" />
   5: </StackPanel>

Cada control Button que he insertado tiene tres propiedades.

La propiedad Name indica el nombre del botón.

La propiedad Tag indica una etiqueta o tag que podemos utilizar en nuestra aplicación si lo deseamos.

Finalmente, la propiedad Style indica el estilo del botón.

Respecto a los estilos cabe señalar algunos detalles que veremos a continuación.

(…Continúa…)

Trabajando con ficheros de recursos e idiomas

Parte I

Parte II

Parte III

 

Trabajando con ficheros de recursos e idiomas (IV)

Creación de ficheros de recursos por idioma

¿En qué idiomas quiero que funcione mi aplicación?.

Parece una pregunta obvia, pero es necesario que nos la hagamos.

En mi caso, español e inglés.

¿Cómo llevar a cabo esto?.

Bastará con crear una carpeta en nuestra aplicación (para tener más ordenados nuestros ficheros de recursos) y crear tantos subdirectorios dentro como idiomas tenga nuestra aplicación.

Cada subdirectorio, pertenecerá a un idioma, teniendo el fichero de recursos el mismo nombre.

Dicho de otro modo.

Nuestra aplicación tendrá una estructura que podría ser por ejemplo igual a la que se indica en la siguiente imagen.

En el caso de nuestro fichero de recursos en español, el contenido del mismo quedará de la siguiente manera:

En el caso de nuestro fichero de recursos en inglés, el contenido del mismo quedará de la siguiente manera:

Si ejecutamos nuestra aplicación, observaremos que ésta se ejecuta en español.

Y es que aún no hemos cambiado el idioma del sistema como idioma preferente, así que volvamos al Panel de Control y a donde nos quedamos anteriormente para cambiar las preferencias del idioma.

Seleccionaré en inglés y lo subiré como preferencia del idioma para hacerlo como lenguaje preferente.

Si ejecutamos nuevamente nuestra aplicación, observaremos que ésta se ejecutará ahora en inglés.

Trabajando con ficheros de recursos e idiomas

Parte I

Parte II

Parte IV

 

Trabajando con ficheros de recursos e idiomas (III)

Consumiendo el fichero de recursos vía XAML

Sin embargo, es posible que (obviando la caja de mensaje), deseemos consumir el fichero de recursos vía XAML en lugar de hacerlo vía código como hemos mostrado anteriormente.

Para ello, por cada control que utilicemos en el código XAML, deberemos utilizar la etiqueta Uid.

La particularidad de hacerlo así es que podemos en el fichero de recursos debemos no sólo indicar el nombre del recursos, sino su propiedad.

Es decir, abriendo el fichero de recursos, las modificaciones que deberemos hacer corresponderían a lo que se indica en la siguiente imagen:

Dentro del código C# correspondiente con la página con la que estamos trabajando, deberemos comentar o eliminar el código del evento OnNavigatedTo para que no interfiera en el ejemplo.

Pero aún falta trabajar con la etiqueta Uid dentro de cada control en el código XAML. Vamos con ello.

Modificando el código XAML

Las modificaciones a realizar son bastante simples.

Basta con agregar una etiqueta Uid en cada control indicándole únicamente el nombre de la etiqueta de recursos identificadora (sin la propiedad a la que queremos vincular).

Es decir, en nuestro, el código XAML quedaría de la siguiente manera:

   1: <Page
   2:     x:Class="Sample3.MainPage"
   3:     IsTabStop="false"
   4:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   5:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   6:     xmlns:local="using:Sample3"
   7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  12:         <Canvas>
  13:             <TextBlock x:Name="tbNombre" Margin="140,120,0,0" Text="Nombre:" 
  14:              FontSize="18" x:Uid="TituloNombre" />
  15:             <TextBox x:Name="txtNombre" Margin="220,120,0,0" Text="Escriba aquí su nombre" />
  16:             <Button x:Name="btnAceptar" Margin="140,180,0,0" Content="Aceptar" 
  17:              BorderThickness="1" Click="btnAceptar_Click_1" x:Uid="BotonAceptar" />
  18:         </Canvas>
  19:     </Grid>
  20:     
  21: </Page>

Como podemos apreciar para el control TextBlock por ejemplo, la etiqueta Uid tiene TituloNombre.

TituloNombre corresponde con TituloNombre.Text en el fichero de recursos.

Basta con ejecutar nuestra aplicación para comprobar y demostrar el comportamiento de nuestra aplicación.

Internacionalización de nuestra aplicación

Una cosa que me choca y que no sé si va a ser así siempre, es que una aplicación Metro funciona en el idioma que está configurado en el sistema operativo.

Es decir, si está en inglés, funcionará en inglés, y si está en español, en español.

Sin embargo, digo que me choca porque a veces y aún trabajando con un sistema operativo en español por ejemplo, es posible que queramos que una aplicación esté en inglés (por la razón que sea).

Indudablemente, si hacemos lo que he mostrado anteriormente, da igual como esté configurado nuestro sistema operativo, ya que nuestra aplicación tirará de los ficheros de recursos y se presentará en el idioma que le indiquemos en ese fichero Resources.resw.

Sin embargo, la mayoría de las veces no va a ser así.

El caso es que no he encontrado la forma de hacer que nuestras aplicaciones Metro funcionen con el idioma que queramos. Me extraña que no se pueda hacer, pero no he encontrado la forma de hacerlo de momento y no sé si es que estará escondida la forma, si es un aspecto relacionado con la beta del producto, o es que simplemente no se puede.

Es por eso que para hacer que nuestro sistema maneje diferentes idiomas, debemos cambiarlo nosotros en la configuración del sistema.

Para cambiar el idioma en nuestro Windows 8, pulsaremos la combinación de teclas Windows + Q para acceder desde allí al Panel de Control, o bien accederemos al Panel de Control directamente.

Dentro del Panel de Control, voy a seleccionar los iconos grandes para localizar más rápidamente la opción que quiero modificar.

Dentro de la ventana que aparece, seleccionaremos la opción Idioma.

Y en esta ventana modificaremos, agregaremos o eliminaremos los idiomas de nuestro sistema.

En mi sistema tengo esta configuración:

Esto significa, que el idioma que aparece como preferente es el español.

Llegados a este punto, hagamos un salto y retornemos al código de nuestra aplicación para volver a este punto una vez hagamos las modificaciones que quiero contar.

(…Continúa…)

Trabajando con ficheros de recursos e idiomas

Parte I

Parte III

Parte IV

 

Trabajando con ficheros de recursos e idiomas (II)

Creando el fichero de recursos

La primera acción a acometer es la de crear el fichero de recursos.

Para ello, vamos a hacer clic con el botón derecho del ratón sobre el proyecto, y vamos a seleccionar la opción Add > New Item o a pulsar la combinación de teclas Ctrl + Shift + A tal y como se indica en la siguiente imagen:

Como nombre del fichero de recursos le he indicado el que normalmente aparece por defecto, Resources.resw.

Aquí conviene hacer un pequeño alto en el camino para explicar alguna cosa al respecto.

Si has trabajado con aplicaciones .NET y has tenido que hacer que tu aplicación se comporte como una aplicación multiidioma, habrás tenido que trabajar con ficheros de recursos.

En .NET (hasta ahora), los ficheros de recursos tenían la extensión resx. Sin embargo, en Metro, esta extensión cambia a resw.

Otro detalle a tener en cuenta, es que con .NET (hasta ahora), los ficheros resx tenían asociado un fichero de código (cs en el caso de C# y vb en el caso de VB). En Metro, eso ya no es así.

Llegado a este punto y estas breves explicaciones, vamos a ver como trabajar con este fichero de recursos.

Preparando el fichero de recursos

Para preparar nuestro fichero de recursos, haremos simplemente doble clic sobre el fichero Resources.resw.

De esta forma, se abrirá el gestor de recursos.

Si hemos trabajado con ficheros resx en .NET, observaremos que el gestor es prácticamente idéntico.

En nuestro ejemplo, hemos agregado las siguientes entradas:

Nota: Intencionadamente le he indicado unos valores recortados de los originales para demostrar su funcionamiento.

Ahora que tenemos la base de nuestra aplicación preparada, vamos a hacerlo funcionar.

Consumiendo el fichero de recursos vía código

No nos vamos a complicar en exceso.

Queremos utilizar el fichero de recursos vía código, así que vamos a ello.

Recordemos un poco alguno de los conceptos Metro explicados en otras entradas.

¿Qué evento se lanza cuando la página es cargada?. Dicho de otra manera aunque no exacta, ¿qué evento se lanza cuando la página obtiene el foco de carga?.

El evento OnNavigatedTo.

Por lo tanto, parece lógico que dentro de este evento, recorramos el fichero de recursos para mostrar en cada control el contenido que queremos localizar.

En nuestro sencillo ejemplo, el código C# del evento OnNavigatedTo para la página MainPage.xaml, quedará de la siguiente manera:

   1: /// <summary>
   2: /// Invoked when this page is about to be displayed in a Frame.
   3: /// </summary>
   4: /// <param name="e">Event data that describes how this page was reached.  The Parameter
   5: /// property is typically used to configure the page.</param>
   6: protected override void OnNavigatedTo(NavigationEventArgs e)
   7: {
   8:     var resourceLoader = new ResourceLoader();
   9:     this.tbNombre.Text = resourceLoader.GetString("TituloNombre");
  10:     this.btnAceptar.Content = resourceLoader.GetString("BotonAceptar");
  11: } // OnNavigatedTo

Como podemos observar, estamos utilizando una clase de nombre ResourceLoader.

Esta clase pertenece al siguiente namespace:

   1: using Windows.ApplicationModel.Resources;

Finalmente, utilizaremos la función GetString() por cada control sobre el que queremos mostrar un texto localizado.

Nuestra aplicación en ejecución quedará de la siguiente manera:

Igualmente, si hubiéramos querido, podríamos haber modificado el texto que aparece en la caja de diálogo o de mensaje.

Bastaría con haber agregado una entrada en el fichero Resources.resw como por ejemplo:

Y en el código C# donde mostramos la caja de mensaje, haber escrito algo similar a esto:

   1: private void btnAceptar_Click_1(object sender, RoutedEventArgs e)
   2: {
   3:     var resourceLoader = new ResourceLoader();
   4:     // Preparamos la caja de mensaje.
   5:     MessageDialog messageDialog = new MessageDialog(string.Format(
   6:                                                                   resourceLoader.GetString("DialogMessageInfo"),
   7:                                                                   this.txtNombre.Text));
   8:     // Mostramos la caja de mensaje.
   9:     messageDialog.ShowAsync();
  10: } // btnAceptar_Click_1

Sin embargo, aún nos quedaría una pregunta que hacernos.

¿Cómo consumir el fichero de recursos vía XAML?.

(…Continúa…)

Trabajando con ficheros de recursos e idiomas

Parte II

Parte III

Parte IV

 

Trabajando con ficheros de recursos e idiomas (I)

Introducción

Cuando desarrollamos aplicaciones Software, es muy normal que nos veamos interesados o incluso obligados, a que nuestra aplicación sea multiidioma con el fin de que pueda ser utilizada por usuarios que hablen diferentes idiomas.

En la siguiente entrada, vamos a ver como desarrollar nuestra aplicación Metro con esta capacidad.

Iniciando nuestra aplicación

Vamos a crear una nueva aplicación Metro, tal y como hemos hecho en las anteriores entradas, con el nombre de Sample3.

Dentro de la página principal de nombre MainPage.xaml, vamos a insertar tres controles.

Un control TextBlock, un control TextBox, y un control Button.

La disposición de estos tres controles en la pantalla es la que se indica en la siguiente imagen.

El código XAML de nuestra página quedará entonces constituido de la siguiente manera:

   1: <Page
   2:     x:Class="Sample3.MainPage"
   3:     IsTabStop="false"
   4:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   5:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   6:     xmlns:local="using:Sample3"
   7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  12:         <Canvas>
  13:             <TextBlock x:Name="tbNombre" Margin="140,120,0,0" Text="Nombre:" FontSize="18" />
  14:             <TextBox x:Name="txtNombre" Margin="220,120,0,0" Text="Escriba aquí su nombre" />
  15:             <Button x:Name="btnAceptar" Margin="140,180,0,0" Content="Aceptar" BorderThickness="1" 
  16:              Click="btnAceptar_Click_1" />
  17:         </Canvas>
  18:     </Grid>
  19:     
  20: </Page>

Lógicamente, en el control Button observamos que hemos indicado un evento.

El código de este evento en la página MainPage.xaml.cs quedará de la siguiente forma:

   1: private void btnAceptar_Click_1(object sender, RoutedEventArgs e)
   2: {
   3:     // Preparamos la caja de mensaje.
   4:     MessageDialog messageDialog = new MessageDialog(string.Format(
   5:                                                                   "Hola {0}",
   6:                                                                   this.txtNombre.Text));
   7:     // Mostramos la caja de mensaje.
   8:     messageDialog.ShowAsync();
   9: } // btnAceptar_Click_1

Nuestra aplicación en ejecución es la que se indica en la siguiente imagen:

Como podemos apreciar, nada excepcional aún.

Ahora bien, supongamos que queremos que nuestros controles TextBlock y Button tengan un contenido diferente del que tenemos por defecto. ¿Cómo lo podemos hacer?.

Para eso está el fichero de recursos que veremos en la siguiente entrada de este pequeño tutorial.

(…Continúa…)

Navegación entre páginas de una aplicación – Avanzado

Parte I

Parte II

Parte III

 

Navegación entre páginas de una aplicación – Avanzado (IV)

Trabajando con OnNavigatedTo en la página principal

Cada vez que navegamos de una página a otra, el evento de la página a la que se navega que se lanza, es el evento OnNavigatedTo.

En nuestro ejemplo, tendremos un código similar al siguiente:

   1: /// <summary>
   2: /// Invoked when this page is about to be displayed in a Frame.
   3: /// </summary>
   4: /// <param name="e">
   5: /// Event data that describes how this page was reached.  The Parameter
   6: /// property is typically used to configure the page.
   7: /// </param>
   8: protected override void OnNavigatedTo(NavigationEventArgs e)
   9: {
  10:     if (e.NavigationMode == NavigationMode.Back)
  11:     {
  12:         // Cargamos el estado previo.
  13:         Planeta planeta = App.Current.Resources["Planeta"] as Planeta;
  14:         if (planeta != null)
  15:         {
  16:             MessageDialog messageDialog = new MessageDialog(String.Format(
  17:                                                             "Ha seleccionado {0} con un diámetro 
  18:                                                              ecuatorial de {1} kilómetros.",
  19:                                                             planeta.Nombre,
  20:                                                             planeta.Diametro));
  21:             messageDialog.ShowAsync();
  22:             // Mostramos la imagen.
  23:             var uri = new Uri("ms-appx:///" + planeta.RutaImagen);
  24:             this.imgPlaneta.Source = new BitmapImage(uri);
  25:             this.tbNombrePlaneta.Text = planeta.Nombre;
  26:             this.tbDiametroPlaneta.Text = String.Format("{0} kilómetros", planeta.Diametro);
  27:         }
  28:     }
  29: } // OnNavigatedTo

De acuerdo al código anterior, observamos varias cosas.

Al principio del todo, podemos preguntar si estamos regresando a la página principal desde otra página o no.

Esto lo logramos con este código:

   1: if (e.NavigationMode == NavigationMode.Back)
   2: {
   3: }

Nota: Recordemos, que en Metro, nosotros debemos crear y gestionar el flujo de navegación de nuestra aplicación.

Una vez dentro de esta cláusula if, podemos realizar la operación u operaciones que consideremos oportunas.

En nuestro caso, he querido obtener el planeta seleccionado, sin embargo, aquí estoy obligado a hacer un alto en el camino.

Alto en el camino que hago por haberme tomado la libertad de gestionar el almacenamiento del planeta seleccionado dentro de la aplicación de una manera particular.

He pensado en este ejemplo, compartir el recurso planeta utilizando la clase App.

El funcionamiento es muy sencillo, basta con utilizar App.Current.Resources[key] para indicar al recurso el valor del mismo o para recuperarlo.

En MainPage.xaml estamos recuperando ese valor, y en BasicPage1.xaml lo asignaremos como veremos más adelante.

Es por eso que en nuestro ejemplo, recuperamos el valor de la clase Planeta de esta forma:

   1: Planeta planeta = App.Current.Resources["Planeta"] as Planeta;

Finalmente y para asegurarnos de que posee un valor válido, preguntamos si planeta es nulo o no.

En el caso de que no sea nulo, mostramos un mensaje en pantalla indicando los detalles del planeta seleccionado, y acto seguido, mostramos esos mismos datos en la página junto a la imagen del planeta seleccionado.

Un detalle a tener en cuenta es la carga de una imagen en Metro.

Como podemos apreciar, la instrucción de carga que hemos utilizado es de la siguiente forma:

   1: var uri = new Uri("ms-appx:///" + planeta.RutaImagen);
   2: this.imgPlaneta.Source = new BitmapImage(uri);

Existen dos maneras de cargar una imagen, a través de ms.appx:///ruta_imagen, o a través de la ruta ms-appdata:///ruta_imagen.

Finalmente, vamos a ver como se comporta BasicPage1.xaml para que podamos jugar con los datos que devuelve hacia MainPage.xaml.

Programando la página secundaria BasicPage1.xaml

El código fuente de esta página secundaria quedará de la siguiente manera:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.IO;
   4: using System.Linq;
   5: using Windows.Foundation;
   6: using Windows.Foundation.Collections;
   7: using Windows.UI.Xaml;
   8: using Windows.UI.Xaml.Controls;
   9: using Windows.UI.Xaml.Controls.Primitives;
  10: using Windows.UI.Xaml.Data;
  11: using Windows.UI.Xaml.Input;
  12: using Windows.UI.Xaml.Media;
  13: using Windows.UI.Xaml.Navigation;
  14:  
  15: namespace Sample2
  16: {
  17:  
  18:     /// <summary>
  19:     /// A basic page that provides characteristics common to most applications.
  20:     /// </summary>
  21:     public sealed partial class BasicPage1 : Sample2.Common.LayoutAwarePage
  22:     {
  23:  
  24:         /// <summary>
  25:         /// Constructor de la clase.
  26:         /// </summary>
  27:         public BasicPage1()
  28:         {
  29:             this.InitializeComponent();
  30:             // Habilitamos la caché.
  31:             this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
  32:             // Cargamos los datos en el control comboBox.
  33:             LoadPlanetas();
  34:         } // BasicPage1 Constructor
  35:  
  36:         /// <summary>
  37:         /// Variable privada encargada de almacenar
  38:         /// los datos del planeta seleccionado.
  39:         /// </summary>
  40:         public Planeta planeta;
  41:  
  42:         /// <summary>
  43:         /// Populates the page with content passed during navigation.  Any saved state is also
  44:         /// provided when recreating a page from a prior session.
  45:         /// </summary>
  46:         /// <param name="navigationParameter">The parameter value passed to
  47:         /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
  48:         /// </param>
  49:         /// <param name="pageState">A dictionary of state preserved by this page during an earlier
  50:         /// session.  This will be null the first time a page is visited.</param>
  51:         protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
  52:         {
  53:         } // LoadState
  54:  
  55:         /// <summary>
  56:         /// Preserves state associated with this page in case the application is suspended or the
  57:         /// page is discarded from the navigation cache.  Values must conform to the serialization
  58:         /// requirements of <see cref="SuspensionManager.SessionState"/>.
  59:         /// </summary>
  60:         /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
  61:         protected override void SaveState(Dictionary<String, Object> pageState)
  62:         {
  63:         } // SaveState
  64:  
  65:         /// <summary>
  66:         /// Método encargado de cargar el listado de 
  67:         /// los planetas del Sistema Solar.
  68:         /// </summary>
  69:         private void LoadPlanetas()
  70:         { 
  71:             SistemaSolar sistemaSolar = new SistemaSolar();
  72:             List<Planeta> planetas = sistemaSolar.GetPlanetas();
  73:             this.cboPlanetas.ItemsSource = planetas;
  74:             this.cboPlanetas.DisplayMemberPath = "Nombre";
  75:             this.cboPlanetas.SelectedValuePath = "Id";
  76:             this.cboPlanetas.SelectedIndex = 0;
  77:         } // LoadPlanetas
  78:  
  79:         /// <summary>
  80:         /// Evento que se lanza al seleccionar un planeta de la lista de planetas.
  81:         /// </summary>
  82:         /// <param name="sender"></param>
  83:         /// <param name="e"></param>
  84:         private void cboPlanetas_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
  85:         {
  86:             this.planeta = (Planeta)(this.cboPlanetas.SelectedItem);
  87:         } // cboPlanetas_SelectionChanged_1
  88:  
  89:         /// <summary>
  90:         /// Evento que ejecutamos al dejar la página.
  91:         /// </summary>
  92:         /// <param name="e"></param>
  93:         protected override void OnNavigatedFrom(NavigationEventArgs e)
  94:         {
  95:             // En nuestro ejemplo, sólo tenemos 1 elemento en los recursos,
  96:             // por lo que la validación es muy sencilla.
  97:             // Basta con ver si hay algún recurso o no creado.
  98:             // Si no lo hay, lo creamos, y en caso contrario, lo reutilizamos.
  99:             if (App.Current.Resources.Count() == 0)
 100:             {
 101:                 App.Current.Resources.Add(
 102:                                           "Planeta", 
 103:                                           this.planeta);
 104:             }
 105:             else
 106:             {
 107:                 App.Current.Resources["Planeta"] = this.planeta;
 108:             }
 109:         } // OnNavigatedFrom
 110:  
 111:     } // BasicPage1
 112:  
 113: } // Sample2

Atendiendo al código de esta página secundaria, observamos que en el constructor, hemos habilitado la caché y hemos llamado a un método que se encargará de cargar los planetas y sus datos (tómese como un ejemplo demo).

   1: /// <summary>
   2: /// Constructor de la clase.
   3: /// </summary>
   4: public BasicPage1()
   5: {
   6:     this.InitializeComponent();
   7:     // Habilitamos la caché.
   8:     this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
   9:     // Cargamos los datos en el control comboBox.
  10:     LoadPlanetas();
  11: } // BasicPage1 Constructor

Nuestra función de carga de los planetas y la carga de todos estos datos en el control ComboBox de la página BasicPage1.xaml queda de la siguiente manera:

   1: /// <summary>
   2: /// Método encargado de cargar el listado de 
   3: /// los planetas del Sistema Solar.
   4: /// </summary>
   5: private void LoadPlanetas()
   6: { 
   7:     SistemaSolar sistemaSolar = new SistemaSolar();
   8:     List<Planeta> planetas = sistemaSolar.GetPlanetas();
   9:     this.cboPlanetas.ItemsSource = planetas;
  10:     this.cboPlanetas.DisplayMemberPath = "Nombre";
  11:     this.cboPlanetas.SelectedValuePath = "Id";
  12:     this.cboPlanetas.SelectedIndex = 0;
  13: } // LoadPlanetas

De igual manera, hemos declarado una variable para trabajar con el planeta seleccionado:

   1: /// <summary>
   2: /// Variable privada encargada de almacenar
   3: /// los datos del planeta seleccionado.
   4: /// </summary>
   5: public Planeta planeta;

Evidentemente, cada vez que modificamos la selección de un planeta, damos cuenta de ellos:

   1: /// <summary>
   2: /// Evento que se lanza al seleccionar un planeta de la lista de planetas.
   3: /// </summary>
   4: /// <param name="sender"></param>
   5: /// <param name="e"></param>
   6: private void cboPlanetas_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
   7: {
   8:     this.planeta = (Planeta)(this.cboPlanetas.SelectedItem);
   9: } // cboPlanetas_SelectionChanged_1

Para finalizar, al igual que en la página principal trabajábamos con el evento OnNavigatedTo, aquí trabajaremos con el evento OnNavigatedFrom.

Este evento será utilizado cada vez que dejemos la página en la que estamos.

Podemos utilizar este evento para muchísimos fines, y uno de ellos según lo he querido yo aquí, para guardar el recurso del planeta seleccionado:

   1: /// <summary>
   2: /// Evento que ejecutamos al dejar la página.
   3: /// </summary>
   4: /// <param name="e"></param>
   5: protected override void OnNavigatedFrom(NavigationEventArgs e)
   6: {
   7:     // En nuestro ejemplo, sólo tenemos 1 elemento en los recursos,
   8:     // por lo que la validación es muy sencilla.
   9:     // Basta con ver si hay algún recurso o no creado.
  10:     // Si no lo hay, lo creamos, y en caso contrario, lo reutilizamos.
  11:     if (App.Current.Resources.Count() == 0)
  12:     {
  13:         App.Current.Resources.Add(
  14:                                   "Planeta", 
  15:                                   this.planeta);
  16:     }
  17:     else
  18:     {
  19:         App.Current.Resources["Planeta"] = this.planeta;
  20:     }
  21: } // OnNavigatedFrom

En este caso, no he querido llamar al método Contains ni a ningún otro método o función para saber si ya hay recursos guardados.

En esta aplicación sólo voy a tener un solo recurso, por lo que simplemente pregunto cuantos hay, y si hay 0, es que el usuario ha accedido a esta página por primera vez, y si hay uno, entonces simplemente sobreescribo el recurso de clave o key "Planeta" con el objeto Planeta seleccionado del control ComboBox.

Nuestra aplicación en ejecución es tal y como se indican en las dos siguientes capturas:

El resultado una vez cerrada la ventana de mensaje de diálogo es de esta manera:

En próximas entradas, espero podamos ver otras cosas diferentes relacionadas con la programación Metro.

Navegación entre páginas de una aplicación – Avanzado

Parte I

Parte II

Parte IV

 

Navegación entre páginas de una aplicación – Avanzado (III)

Agregando imágenes a nuestro proyecto

Las imágenes de nuestra aplicación las podemos situar donde consideremos oportuno, pero lo más obvio y rápido es situarla en la carpeta Images.

En el Explorador de Soluciones, encontrará un botón que indica Show All Files.

Esta opción nos permite ver los archivos visibles en el proyecto y los que no son visibles (porque no se han cargado) en el mismo.

En mi carpeta Images he colocado una imagen por cada planeta, por lo que haciendo clic sobre Show All Files, me he situado sobre la carpeta Images y he pulsado el botón derecho del ratón sobre cada imagen y he elegido la opción Include in Project para incluirlas en el proyecto.

Preparando la página principal

Nos hemos centrado bastante en la página secundaria y en las clases que utilizaremos para cargar datos, pero aún no nos hemos detenido en la página principal.

Para nuestra página principal, he querido agregar una imagen lateral en el lado izquierdo con los diferentes planetas del sistema solar, a modo de imagen genérica para darle un aspecto menos tosco a nuestra aplicación.

Además, he agregado un control HyperlinkButton para que al pulsar sobre él, podamos ir a la página secundaria BasicPage.xaml.

También he agregado un control Button para que al hacer clic sobre él, cerremos la aplicación.

Y para finalizar, he agregado un control Image que mostrará la imagen del planeta seleccionado en la página secundaria, y dos controles TextBlock para mostrar los datos del planeta seleccionado.

Nuestra ventana quedará de la siguiente manera.

Y el código XAML asociado a MainPage.xaml corresponderá con el siguiente código.

   1: <Page
   2:     x:Class="Sample2.MainPage"
   3:     IsTabStop="false"
   4:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   5:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   6:     xmlns:local="using:Sample2"
   7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="Black">
  12:         <Image HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" 
  13:                Source="ms-appx:///Images/Planetas_Sistema_Solar.png" Height="598" Width="202" />
  14:         <Canvas>
  15:             <HyperlinkButton Margin="300,100,0,0" Content="Seleccione un planeta del Sistema Solar" 
  16:                              Foreground="DarkGoldenrod" FontSize="20" Click="HyperlinkButton_Click_1" />
  17:             <Button x:Name="btnSalir" Content="Volver a casa" Canvas.Left="40" Canvas.Top="620" 
  18:                     FontSize="16" BorderThickness="1" Background="Black" BorderBrush="BlueViolet" 
  19:                     Foreground="DarkSlateBlue" Click="btnSalir_Click_1" />
  20:             <Image x:Name="imgPlaneta" Height="200" Canvas.Left="400" Canvas.Top="220" Width="200" />
  21:             <TextBlock x:Name="tbNombrePlaneta" Canvas.Top="440" Canvas.Left="400" 
  22:                        Foreground="DarkOrange" FontSize="24" />
  23:             <TextBlock x:Name="tbDiametroPlaneta" Canvas.Top="480" Canvas.Left="400" 
  24:                        Foreground="Orange" FontSize="20" />
  25:         </Canvas>
  26:     </Grid>
  27: </Page>

Programando la página principal

Una vez que hemos preparado la interfaz de usuario en ambas páginas y que hemos preparado las clases en las que vamos a cargar los datos, vamos a escribir el código de la página principal.

En primer lugar nos centraremos en el constructor de la clase MainPage.xaml.

Con el fin de que accedamos a los datos de la página que teníamos cargados al regresar a nuestra página, debemos cachear la instancia de nuestra página.

Para ello, utilizaremos la siguiente instrucción:

   1: this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;

Nuestro constructor quedará por lo tanto de la siguiente forma:

   1: /// <summary>
   2: /// Constructor de la clase.
   3: /// </summary>
   4: public MainPage()
   5: {
   6:     this.InitializeComponent();
   7:     // Habilitamos la caché.
   8:     this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
   9: } // MainPage Constructor

A continuación, vamos a preparar los eventos de los dos controles de la página principal, el del control Button y el del control HyperlinkButton.

El código de estos dos eventos quedarán de la siguiente manera:

   1: private void btnSalir_Click_1(object sender, RoutedEventArgs e)
   2: {
   3:     // Cerramos la aplicación.
   4:     Application.Current.Exit();
   5: } // btnSalir_Click_1
   6:  
   7: private void HyperlinkButton_Click_1(object sender, RoutedEventArgs e)
   8: {
   9:     // Navegamos a la página BasicPage1.
  10:     this.Frame.Navigate(typeof(BasicPage1));
  11: } // HyperlinkButton_Click_1

Nota: Aunque aquí me he sacado de la chistera el botón de cerrar la aplicación, esto en Metro no está permitido, y nuestra aplicación no pasaría la validación del Store de Windows 8. Ojo con esto.

El último evento a tener en cuenta es el evento OnNavigatedTo de la página.

(…Continúa…)

Navegación entre páginas de una aplicación – Avanzado

Parte I

Parte III

Parte IV

 

Navegación entre páginas de una aplicación – Avanzado (II)

Dando forma a la aplicación

No obstante, he comentado anteriormente que en esta aplicación vamos a cargar una serie de datos.

Para tal propósito, vamos a crear una clase de nombre Planeta que contendrá información de los planetas con sus respectivos datos, como son un identificador del planeta (que no utilizaremos en este ejemplo), un nombre de planeta, un diámetro del planeta, y una ruta de la imagen del planeta para mostrarla en la página principal una vez hayamos seleccionado el planeta.

Para agregar la clase Planeta a la aplicación, vamos a hacer clic con el botón derecho del ratón sobre el proyecto del Explorador de Soluciones, y vamos a seleccionar la opción Add > New Item, o bien, podemos utilizar la combinación de teclas Ctrl + Shift + A.

Buscaremos como elemento a agregar una clase, y como nombre de la misma, Planeta, tal y como se indica en la siguiente imagen.

Repetiremos la misma acción pero creando una clase de nombre SistemaSolar. Esta segunda clase será la encargada de cargar los datos de cada uno de los planetas, en este caso, pertenecientes al Sistema Solar.

El código asociado a nuestra clase Planeta quedará de la siguiente manera:

   1: namespace Sample2
   2: {
   3:  
   4:     /// <summary>
   5:     /// Clase pública sellada que indica los planetas del Sistema Solar.
   6:     /// </summary>
   7:     public sealed class Planeta
   8:     {
   9:  
  10:         #region CONSTRUCTOR
  11:  
  12:             /// <summary>
  13:             /// Constructor de la clase.
  14:             /// </summary>
  15:             /// <param name="id">
  16:             /// Identificador único para cada planeta.
  17:             /// </param>
  18:             /// <param name="nombre">
  19:             /// Nombre del planeta.
  20:             /// </param>
  21:             /// <param name="diametro">
  22:             /// Diámetro ecuatorial del planeta medido en kilómetros.
  23:             /// </param>
  24:             /// <param name="rutaImagen">
  25:             /// Ruta de la imagen a mostrar en la aplicación.
  26:             /// </param>
  27:             public Planeta(
  28:                            int id,
  29:                            string nombre,
  30:                            int diametro,
  31:                            string rutaImagen)
  32:             {
  33:                 this.Id = id;
  34:                 this.Nombre = nombre;
  35:                 this.Diametro = diametro;
  36:                 this.RutaImagen = rutaImagen;
  37:             } // Planeta Constructor
  38:  
  39:         #endregion
  40:  
  41:         #region PROPERTIES
  42:  
  43:             /// <summary>
  44:             /// Propiedad pública que indica el identificador del planeta.
  45:             /// </summary>
  46:             public int Id { get; set; }
  47:  
  48:             /// <summary>
  49:             /// Propiedad pública que indica el nombre del planeta.
  50:             /// </summary>
  51:             public string Nombre { get; set; }
  52:  
  53:             /// <summary>
  54:             /// Propiedad pública que indica el diámetro ecuatorial 
  55:             /// medido en kilómetros.
  56:             /// </summary>
  57:             public int Diametro { get; set; }
  58:  
  59:             /// <summary>
  60:             /// Propiedad pública que indica la ruta en la que se 
  61:             /// encuentra la imagen del planeta a mostrar en la 
  62:             /// aplicación.
  63:             /// </summary>
  64:             public string RutaImagen { get; set; }
  65:  
  66:         #endregion
  67:  
  68:     } // Planeta
  69:  
  70: } // Sample2

El código asociado a nuestra clase SistemaSolar por su parte, quedará de esta otra manera:

   1: namespace Sample2
   2: {
   3:  
   4:     using System.Collections.Generic;
   5:  
   6:  
   7:     /// <summary>
   8:     /// Clase pública sellada que permite simular la carga de datos 
   9:     /// de los planetas del Sistema Solar.
  10:     /// </summary>
  11:     public sealed class SistemaSolar
  12:     {
  13:  
  14:         #region CONSTRUCTORS
  15:  
  16:             /// <summary>
  17:             /// Constructor de la clase.
  18:             /// </summary>
  19:             public SistemaSolar()
  20:             {
  21:             } // SistemaSolar Constructor
  22:  
  23:         #endregion
  24:  
  25:         #region FUNCTIONS
  26:  
  27:             /// <summary>
  28:             /// Función que permite obtener una colección de
  29:             /// planetas pertenecientes al Sistema Solar.
  30:             /// </summary>
  31:             /// <returns>
  32:             /// Devolvemos una colección de planetas.
  33:             /// </returns>
  34:             public List<Planeta> GetPlanetas()
  35:             {
  36:                 // Creamos la colección de planetas.
  37:                 List<Planeta> planetas = new List<Planeta>();
  38:                 planetas.Add(new Planeta(1, "Júpiter", 142984, "Images/Jupiter.png"));
  39:                 planetas.Add(new Planeta(2, "Marte", 6787, "Images/Marte.png"));
  40:                 planetas.Add(new Planeta(3, "Mercurio", 4878, "Images/Mercurio.png"));
  41:                 planetas.Add(new Planeta(4, "Neptuno", 49538, "Images/Neptuno.png"));
  42:                 planetas.Add(new Planeta(5, "Plutón", 2390, "Images/Pluton.png"));
  43:                 planetas.Add(new Planeta(6, "Saturno", 120536, "Images/Saturno.png"));
  44:                 planetas.Add(new Planeta(7, "Tierra", 12756, "Images/Tierra.png"));
  45:                 planetas.Add(new Planeta(8, "Urano", 51108, "Images/Urano.png"));
  46:                 planetas.Add(new Planeta(9, "Venus", 12100, "Images/Venus.png"));
  47:                 // Devolvemos la colección de planetas.
  48:                 return planetas;
  49:             } // GetPlanetas
  50:  
  51:         #endregion
  52:  
  53:     } // SistemaSolar
  54:  
  55: } // Sample2

Si observamos el código de esta segunda clase, veremos que en la carga de los datos, le estamos indicando una ruta de imágenes que corresponde cada una de ellas, con la imagen de cada planeta.

(…Continúa…)

Navegación entre páginas de una aplicación – Avanzado

Parte II

Parte III

Parte IV

 

Navegación entre páginas de una aplicación – Avanzado (I)

Introducción

Otro de los aspectos que debemos controlar a la hora de desarrollar aplicaciones en Windows 8 con Metro es la capacidad o posibilidad que tenemos los programadores a la hora de jugar con los datos de ida y vuelta.

A continuación, vamos a ver como recargar datos entre páginas y como tratarlos.

Nota: Para este capítulo y sus subcapítulos, se entiende que el lector ya tiene algún conocimiento de Visual Studio 2012 y que para ello ha leído y comprendido la anterior entrada "Navegación entre páginas de una aplicación - Introducción" o cualquier otra documentación similar de Internet.

Objetivo del ejemplo

El objetivo de este ejemplo es el de preparar una página principal de aplicación y una página secundaria.

En la página secundaria tendremos una colección de planetas que tendrá entre otros datos, su nombre, su diámetro y la ruta de la imagen del planeta seleccionado para mostrarla en la página principal.

Cuando regresemos de esa página secundaria a la página principal, cargaremos en ésta los datos del planeta seleccionado y su imagen como decía anteriormente.

Parece sencillo ¿verdad?.

Pues vamos a ello.

Preparando la aplicación

Iniciaremos un nuevo proyecto con Visual Studio 2012 con las plantillas de Windows Metro style y en concreto utilizando una plantilla vacía (Blank App (XAML)) en C#.

Como nombre de proyecto, Sample2.

Esta plantilla habrá creado una página de nombre MainPage.xaml.

La siguiente acción que realizaremos será la de agregar una nueva página de tipo básica a la aplicación, agregando para ello una página de tipo Basic Page.

Nota: Repase el capítulo de introducción que anteriormente se comentó si tiene alguna duda para crear el proyecto.

Como nombre de la nueva página que queremos añadir, elegiremos el nombre que Visual Studio 2012 nos recomienda por defecto, y que es BasicPage1.xaml.

Es posible que aparezca un mensaje de aviso. Si ocurre así, responderemos afirmativamente.

Una vez hecho esto, vamos a compilar nuestra solución, y acto seguido vamos a situarnos en el código XAML de la página que acabamos de crear, es decir, en el fichero BasicPage1.xaml.

Recordemos que en el Explorador de Soluciones tendremos algo similar a lo que se indica en la siguiente imagen.

Centrándonos en el código XAML de BasicPage1.xaml, vamos a buscar el control TextBlock con el nombre pageTitle, y vamos a cambiar su propiedad Text a "Seleccione un planeta".

A continuación, agregaremos a la página BasicPage1.xaml, un control TextBlock y un control ComboBox.

El control TextBlock lo utilizaremos para mostrar un texto genérico que en nuestro caso es "Listado de planetas:".

El control ComboBox lo utilizaremos para agregar en dicho control, una lista de planetas que habremos cargado previamente simulando una carga de datos sobre este control.

El aspecto de nuestra página BasicPage1.xaml será similar al siguiente:

El código XAML asociado a la página será similar al siguiente:

   1: <common:LayoutAwarePage
   2:     x:Name="pageRoot"
   3:     x:Class="Sample2.BasicPage1"
   4:     DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
   5:     IsTabStop="false"
   6:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   7:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   8:     xmlns:local="using:Sample2"
   9:     xmlns:common="using:Sample2.Common"
  10:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  11:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  12:     mc:Ignorable="d">
  13:  
  14:     <Page.Resources>
  15:         <x:String x:Key="AppName">My Application</x:String>
  16:     </Page.Resources>
  17:  
  18:     <Grid Style="{StaticResource LayoutRootStyle}">
  19:         <Grid.RowDefinitions>
  20:             <RowDefinition Height="140"/>
  21:             <RowDefinition Height="*"/>
  22:         </Grid.RowDefinitions>
  23:  
  24:         <Grid>
  25:             <Grid.ColumnDefinitions>
  26:                 <ColumnDefinition Width="Auto"/>
  27:                 <ColumnDefinition Width="*"/>
  28:             </Grid.ColumnDefinitions>
  29:             <Button x:Name="backButton" Click="GoBack" 
  30:                     IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" 
  31:                     Style="{StaticResource BackButtonStyle}"/>
  32:             <TextBlock x:Name="pageTitle" Grid.Column="1" Text="Seleccione un planeta" 
  33:                        Style="{StaticResource PageHeaderTextStyle}"/>
  34:         </Grid>
  35:         <TextBlock HorizontalAlignment="Left" Margin="60,40,0,0" Grid.Row="1" 
  36:                    TextWrapping="Wrap" Text="Listado de planetas:" VerticalAlignment="Top" 
  37:                    FontSize="20" Foreground="LightCyan" />
  38:         <ComboBox x:Name="cboPlanetas" HorizontalAlignment="Left" Margin="60,80,0,0" 
  39:                   Grid.Row="1" VerticalAlignment="Top" Width="180" FontSize="16" 
  40:                   SelectionChanged="cboPlanetas_SelectionChanged_1" ItemsSource="{Binding}" />
  41:  
  42:         <VisualStateManager.VisualStateGroups>
  43:  
  44:             <VisualStateGroup x:Name="ApplicationViewStates">
  45:                 <VisualState x:Name="FullScreenLandscape"/>
  46:                 <VisualState x:Name="Filled"/>
  47:  
  48:                 <VisualState x:Name="FullScreenPortrait">
  49:                     <Storyboard>
  50:                         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
  51:                                                        Storyboard.TargetProperty="Style">
  52:                             <DiscreteObjectKeyFrame KeyTime="0" 
  53:                                                     Value="{StaticResource PortraitBackButtonStyle}"/>
  54:                         </ObjectAnimationUsingKeyFrames>
  55:                     </Storyboard>
  56:                 </VisualState>
  57:  
  58:                 <VisualState x:Name="Snapped">
  59:                     <Storyboard>
  60:                         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
  61:                                                        Storyboard.TargetProperty="Style">
  62:                             <DiscreteObjectKeyFrame KeyTime="0" 
  63:                                                     Value="{StaticResource SnappedBackButtonStyle}"/>
  64:                         </ObjectAnimationUsingKeyFrames>
  65:                         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" 
  66:                                                        Storyboard.TargetProperty="Style">
  67:                             <DiscreteObjectKeyFrame KeyTime="0" 
  68:                                                     Value="{StaticResource SnappedPageHeaderTextStyle}"/>
  69:                         </ObjectAnimationUsingKeyFrames>
  70:                     </Storyboard>
  71:                 </VisualState>
  72:             </VisualStateGroup>
  73:         </VisualStateManager.VisualStateGroups>
  74:     </Grid>
  75: </common:LayoutAwarePage>

(…Continúa…)

Navegación entre páginas de una aplicación - Introducción

Parte I

Parte II

 

 

Navegación entre páginas de una aplicación - Introducción (III)

Pasando datos de una página a otra

Dentro de nuestra página Prueba.xaml.cs observaremos que por defecto, Visual Studio 2012 ha agregado dos métodos, uno de nombre LoadState y otro llamado SaveState.

De momento, vamos a obviar ambos métodos, y vamos a centrar nuestra atención en un evento que por defecto no existe. Hablo del evento OnNavigatedTo.

Para ello, vamos a escribir dentro del código C# de nuestra página, la palabra reservada override y seleccionaremos el método mencionado anteriormente.

Una vez hecho esto, tendremos un código similar al siguiente:

   1: protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     base.OnNavigatedTo(e);
   4: }

Obviamente, deberemos realizar algún ajuste en el contenido de este evento.

Éste quedará de la siguiente forma:

   1: protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     this.txtSaludo.Text = String.Format("Hola {0}", e.Parameter.ToString());
   4: } // OnNavigatedTo

Con esta instrucción, mostraremos en la página Prueba.xaml el contenido del control TextBox que indicamos en la página MainPage.xaml una vez hayamos pulsado el control Button de esta última.

Podemos ejecutar nuestra aplicación pulsando la tecla F5 para ver el resultado obtenido.

Daños colaterales

Sin embargo, nuestra aplicación tiene un daño colateral.

Si ejecutamos nuestra aplicación, observaremos que cuando pulsamos el botón de volver de nuestra página Prueba.xaml, el texto que teníamos en el control TextBox de nuestra página MainPage.xaml ha desaparecido.

Esto es debido a que la página MainPage.xaml no ha sido cacheada, por lo que si queremos que nuestra página principal MainPage.xaml no pierda el contenido indicado en la misma, deberemos ejecutar una sencilla instrucción que permita cachear dicha página.

Para tal fin y dentro del constructor de nuestra página principal (en nuestro caso), vamos a habilitar la opción de cachear la página.

La porción de código de nuestro constructor quedaría de la siguiente manera:

   1: public MainPage()
   2: {
   3:     this.InitializeComponent();
   4:     this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
   5: } // MainPage

OnNavigatedTo y OnNavigatedFrom

Otro daño colateral que mucho me temo, se debe a un bug de la versión preliminar de Visual Studio 2012 y sus plantillas (en la versión anterior beta de Visual Studio 2012 no ocurría), es el hecho de que ejecutando nuestra aplicación se produzca una excepción al volver de Prueba.xaml a MainPage.xaml.

Para comprobar esta excepción, ejecute la aplicación desde Visual Studio 2012 pulsando la tecla F5, y escriba un nombre o texto en la caja de texto de MainPage.xaml y pulse el botón correspondiente.

Una vez mostrada la página Prueba.xaml, regrese a la página MainPage.xaml nuevamente.

Observará entonces que se produce una excepción.

El motivo de que se lance esta excepción es que para la clase autogenerada por Visual Studio 2012 llamada LayoutAwarePage.cs, y en su evento OnNavigatedFrom, la variable privada _pageKey vale en este caso null.

Pero antes de continuar repasemos los dos eventos que debemos conocer.

Cabe recordar que hay dos eventos dentro de una página que pueden ser sobre escritos y que tienen los nombres de OnNavigatedTo y OnNavigatedFrom.

Estos dos eventos los utilizaremos para navegar hacia una página o desde una página. En concreto, utilizaremos OnNavigatedTo cuando la página hacia la que se navega se convierte en primer plano, y OnNavigatedFrom cuando se abandona el primer plano.

Es normal y habitual utilizar estos dos eventos para cargar datos o almacenar un contexto determinado al abandonar la página sobre la que se estaba trabajando.

Por lo tanto, y después de lo comentado, lo normal es que se lance OnNavigatedTo y no OnNavigatedFrom. De hecho, el código no entra en OnNavigatedTo. Es por esto que se genera la excepción indicada anteriormente.

Regresando al problema anterior, soy honesto al decir que no tengo del todo claro si la ejecución del código es ahora mismo la correcta o si se debe a algún bug de Visual Studio 2012 y de .NET, pero la siguiente solución que voy a dar al problema con el que nos hemos encontrado resuelve el problema que acabamos de ver, al menos momentáneamente.

Bastaría simplemente con comprobar primero si _pageKey vale null o no, y en el caso de que no valga null, ejecutar la instrucción que da la excepción.

Nuestro código quedaría por lo tanto de la siguiente manera:

   1: protected override void OnNavigatedFrom(NavigationEventArgs e)
   2: {
   3:     var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
   4:     var pageState = new Dictionary<String, Object>();
   5:     this.SaveState(pageState);
   6:     if (_pageKey != null)
   7:     {
   8:         frameState[_pageKey] = pageState;
   9:     }
  10: } // OnNavigatedFrom

Y hasta aquí lo que podríamos entender como toma de contacto Metro.

En próximas entradas, iremos mejorando algunas de las cosas comentadas y profundizando un poco más en el desarrollo Metro.

Navegación entre páginas de una aplicación - Introducción

Parte I

Parte III

 

 

Navegación entre páginas de una aplicación - Introducción (II)

Agregando funcionalidad a la página principal

Lo primero que vamos a hacer es agregar algo de funcionalidad a la página principal.

Lo más típico es agregar algún tipo de control al formulario principal y la posibilidad de abrir la segunda página Prueba.xaml desde esta página.

Para ese fin, vamos a hacer doble clic sobre MainPage.xaml con el fin de que se abra esta página en nuestro diseñador.

Una vez hecho esto, vamos a agregar en esta página, un control TextBlock, un control TextBox, y un control Button.

El objetivo es que escribamos algo en la caja de texto (control TextBox), y al pulsar el control Button, vayamos a la página Prueba.xaml y mostremos en esa página el texto escrito en la caja de texto. Algo simple y sencillo como podemos ver.

El código XAML de esta página (MainPage.xaml) es el que se puede ver a continuación:

   1: <Page
   2:     x:Class="Sample1.MainPage"
   3:     IsTabStop="false"
   4:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   5:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   6:     xmlns:local="using:Sample1"
   7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  12:         <TextBlock HorizontalAlignment="Left" Margin="20,40,0,0" TextWrapping="Wrap" 
  13:                    Text="Escriba su nombre:" VerticalAlignment="Top" FontSize="24" />
  14:         <TextBox HorizontalAlignment="Left" Margin="240,40,0,0" TextWrapping="Wrap" 
  15:                  Text="" VerticalAlignment="Top" Width="300" />
  16:         <Button Content="Saludar" HorizontalAlignment="Left" Margin="20,90,0,0" 
  17:                 VerticalAlignment="Top" BorderThickness="1" FontSize="20" 
  18:                 Foreground="LightBlue" BorderBrush="Beige" />
  19:     </Grid>
  20: </Page>

Si ejecutamos nuestra aplicación, observaremos que aún no hemos cargado la página Prueba.xaml ni hemos realizado ninguna acción concreta.

Antes de esto, vamos a preparar nuestra página Prueba.xaml.

Preparando nuestra página secundaria

Nuestra página secundaria, Prueba.xaml, tendrá un aspecto similar al que se presenta en la siguiente imagen:

Por esta razón, lo primero que vamos a hacer es cambiar el texto que aparece en el título de nuestra página.

Para ello, vamos a buscar un control de tipo TextBlock que tiene la propiedad Name como pageTitle, y vamos a cambiar su propiedad Text a Prueba. Servirá cualquier nombre, pero quiero poner este para que veamos claramente que se carga la segunda página de nuestro proyecto.

Para completar nuestra aplicación y puesto que cuando pulsemos el botón de nuestra primera página y página principal, MainPage.xaml, queremos que nos muestre un texto, vamos a agregar además un control TextBlock para que haga la función de mostrar ese texto.

Para ello, escribiremos el siguiente código XAML.

   1: <StackPanel Grid.Row="1" Margin="120,20,20,20">
   2:     <TextBlock HorizontalAlignment="Left" Name="txtSaludo" Text="" FontSize="24" />
   3: </StackPanel>

Cabe descacar que de acuerdo a la página que hemos creado y por defecto en su creación, ésta tiene un Grid que actúa como panel principal en el que se encuentran dos filas.

La primera de esas filas está reservada para el botón de retroceso y que nos llevará a la página que ha llamado a esta y que en nuestro caso será MainPage.xaml, y una segunda segunda fila que contendrá el resto de la página que es donde hemos querido insertar nuestros controles.

Esto lo logramos utilizando la instrucción XAML Grid.Row="número_de_fila".

Volvamos nuevamente a nuestra página principal MainPage.xaml.

Agregando eventos a la página principal

Nos hemos centrado bastante en el diseño de nuestras dos páginas, sin embargo y para que haya funcionalidad, debemos hacer aún algunos pequeños ajustes.

Por un lado, la caja de texto o control TextBox de la página MainPage.xaml no posee ningún nonbre. Dicho de otra forma, cuando queramos hacer referencia a este objeto o control, no tendremos forma de hacerlo, por lo que agregaremos al código XAML una propiedad Name.

El código de nuestro control TextBox para nuestra página XAML MainPage.xaml de la siguiente manera.

   1: <TextBox x:Name="txtNombre" HorizontalAlignment="Left" Margin="240,40,0,0" 
   2:          TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300" />

En otro orden de cosas, nuestro control Button no tiene asociado ningún evento.

Lo que queremos, es que al hacer clic sobre el botón, éste llame y cargue la página Prueba.xaml que hemos creado.

Para ello, vamos a hacer un clic sobre el control Button del código XAML, y vamos a acudir a la ventana de Propiedades.

Dentro de esta ventana, vamos a situarnos en los eventos del control (el icono que simula un rayo) y vamos a hacer doble clic sobre la caja de texto a la derecha de Click.

De esta forma, agregaremos un evento Click asociado a nuestro control Button, de tal manera que al hacer clic sobre el botón, carguemos la página Prueba.xaml que es el objetivo buscado.

Una vez hecho esto, se abrirá el código asociado a nuestro código XAML, es decir, para MainPage.xaml, el fichero de código C# MainPage.xaml.cs.

   1: private void Button_Click_1(object sender, RoutedEventArgs e)
   2: {
   3: }

Nota adicional: Como acabamos de hacer diferentes acciones como agregar un nombre a los controles y un evento, antes de continuar se recomienda compilar la aplicación para que los ajustes y cambios estén bien acoplados a la aplicación.

Bien, llegados a este punto, ha llegado el momento de programar nuestro evento Click sobre el control Button.

Programando el evento del control Button de nuestra página principal

¿Qué queremos hacer?.

Sencillamente, que al hacer clic sobre el control Button, llamemos a la página Prueba.xaml.

Sin embargo, debemos tener en cuenta algunos detalles.

Un detalle funcional de nuestro ejemplo que no obligado, es obligar a que en la caja de texto o control TextBox, tengamos algo de texto. En caso contrario, impediremos la llamada y consiguiente carga de la página Prueba.xaml.

El segundo de los detalles y de carácter funcional puro, es que cuando llamemos a la página Prueba.xaml, lo hagamos porque la caja de texto o control TextBox posee un texto, y que ese texto viaje a dicha ventana y nos lo muestre, de forma que cerremos el círculo de navegación entre una página y otra.

Para llevar a cabo ambas operaciones, vamos a escribir el siguiente código fuente en C# asociado con el evento Click del control Button.

   1: private void Button_Click_1(object sender, RoutedEventArgs e)
   2: {
   3:     if (string.IsNullOrWhiteSpace(this.txtNombre.Text))
   4:     {
   5:         Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog(
   6:                                                                     "Debe escribir un nombre válido.",
   7:                                                                     "Sample 1");
   8:         var response = messageDialog.ShowAsync();
   9:     }
  10:     else
  11:     {
  12:         this.Frame.Navigate(typeof(Prueba), this.txtNombre.Text);
  13:     }
  14: } // Button_Click_1

Si ejecutamos nuestra aplicación, observaremos que nuestra aplicación trabajar de momento, tal y como queremos.

Observando el código de la llamada, vemos que además de llamar a la página Prueba u tilizando el método Navigate, le estamos indicando el texto de nuestro control TextBox.

this.Frame.Navigate(typeof(Prueba), this.txtNombre.Text);

Sin embargo, nuestra página Prueba.xaml aún no es consciente de que la estamos indicando nada (concretamente y en nuestro caso, el contenido de nuestro control TextBox en nuestra página principal MainPage.xaml).

(…Continúa…)

Nota preliminar del autor: Las entradas y subentradas que he elaborado constituyen una toma de contacto con Metro y Visual Studio 2012, pero no están pensadas pensando en la interfaz Metro. Por esta razón, las entradas tratan de abordar conceptos de una forma de desarrollar una aplicación Metro, pero debemos tener en cuenta que a la hora de desarrollar una aplicación Metro, ésta debe seguir unas normas y pautas de diseño por las cuales, Microsoft podría rechazar nuestra aplicación.

Navegación entre páginas de una aplicación - Introducción

Parte II

Parte III

 

 

Navegación entre páginas de una aplicación - Introducción (I)

Introducción

Vamos a empezar una serie de entradas que tienen relación con las comunes y típicas operaciones y acciones básicas de programación con las que deberemos enfrentarnos a la hora de desarrollar cualquier utilidad o aplicación para Windows 8.

En esta primera entrada y para abrir bocas, vamos a trabajar con una aplicación que tenga más de una ventana, y vamos a interactuar con ellas, de forma que aprendamos a navegar entre las diferentes ventanas de nuestra aplicación, y podamos manipular datos de una ventana desde otra.

Nota adicional del autor: Estas entradas están creadas con la versión preliminar del entorno de desarrollo Visual Studio 2012 y del sistema operativo Windows 8, por lo que podría haber diferencias entre lo que se expone en todas las entradas y la versión definitiva de ambos productos.

Crear nuestro proyecto con Visual Studio 2012

Lo primero que deberemos hacer es crear nuestro proyecto con Visual Studio 2012.

Para ello, crearemos un proyecto en C# de tipo Windows Metro Style y como plantilla, utilizaremos la plantilla Blank App (XAML).

En el Explorador de Soluciones, encontraremos nuestro proyecto recién creado con todos los archivos creados por defecto.

Agregar una nueva Page o página a nuestro proyecto

El concepto de Window o ventana en aplicaciones Metro ha dejado paso al concepto de Page o página.

Si prestamos atención al proyecto que hemos creado, observaremos que por defecto, la plantilla Blank App (XAML), ha creado una página de nombre MainPage.xaml.

Esta página tiene asociado un fichero de código que para C# será MainPage.xaml.cs y que para VB será MainPage.xaml.vb.

Nosotros por nuestra parte, vamos a agregar una nueva página de nombre Prueba, y que en nuestro caso será Prueba.xaml, y como código asociado, Prueba.xaml.cs.

Para realizar esto, vamos a hacer clic con el botón derecho del ratón sobre el proyecto del Explorador de Soluciones, y vamos a seleccionar la opción Add > New Item, o bien, podemos utilizar la combinación de teclas Ctrl + Shift + A.

Una vez hecho esto, seleccionaremos la plantilla Basic Page para crear una página básica, y como nombre tal y como mencioné anteriormente, pondremos Prueba.

En este caso por lo tanto, trabajaremos con una página de nombre Prueba.xaml, y con un código asociado en C# de nombre Prueba.xaml.cs.

Cuando hagamos esto, Visual Studio 2012 nos mostrará un mensaje por pantalla en el que nos facilita la vida agregando por nosotros una serie de archivos y dependencias para trabajar con esta página. En caso contrario, deberíamos llevar a cabo operaciones manuales con tal propósito. En nuestro caso, vamos a responder a esta sugerencia.

Observaremos entonces, que dentro de la carpeta Common de nuestro proyecto, Visual Studio 2012 se ha encargado de agregar una serie de archivos que nos ayudará a la hora de trabajar con nuestras páginas.

Una vez hecho esto, observaremos que en Prueba.xaml hay un mensaje.

Para visualizar correctamente dentro del diseñador de Visual Studio 2012 nuestra nueva página Prueba recién creada, vamos a recompilar nuestra solución.

Iniciando nuestra aplicación

Llegados a este punto, vamos a ejecutar nuestra aplicación.

Esto lo lograremos haciendo clic sobre la tecla F5.

Si lo hacemos veremos que aparece una ventana de color oscuro y que pertenece a MainPage.xaml, y es que aunque tengamos dos páginas en nuestra aplicación, todavía no hemos agregado ninguna funcionalidad ni control a ninguna de ellas, así que vamos a darle un poco de forma a nuestra aplicación.

(…Continúa…)

Introducción

Quizás seas de los atrevidos y/o afortunados que se han aventurado a instalar Visual Studio 2012 en alguna de sus versiones previas.

Si es así, te animo a que cuando encuentres un bug, un error o un funcionamiento extraño, te animes a enviarlo a Microsoft con el fin de que aparezca resuelto en la versión final del producto.

Microsoft recomienda NO utilizar su sitio Connect y sí esta herramienta.


Microsoft Visual Studio 2012 Feedback Tool

Este complemento de Microsoft, nos permite enviar o reportar a Microsft de forma rápida y fácilmente un bug.

El plugin se instala en Visual Studio 2012 desde donde podremos enviar los errores y bugs que encontremos al equipo de desarrollo de Microsoft.

Podrás acceder a esta herramienta para su descarga desde este enlace (360 Kb).

Recuerda además, que dispones de un fórum donde podrás indicar tus sugerencias y mejoras de cara a las futuras versiones de Visual Studio. Podrás acceder a este sitio en este enlace.

Publicado por Jorge Serrano | con no comments

Introducción

Este fin de semana he estado cacharreando con Windows 8 y me he encontrado con una pregunta.

¿Qué le pasa a un usuario que se enfrenta por primera vez a Windows 8?

La respuesta es simple, puedes experimentar contigo o con algún familiar o amigo cercano, y observarás que aunque es un sistema operativo bastante intuitivo, al principio choca.

Y choca porque para acceder a algunas partes del sistema con las que estábamos acostumbrados y familiarizados, tenemos que hacer algún que otro rodeo.

Sin embargo, estos rodeos se pueden romper con combinaciones de teclas o atajos de teclado, los cuáles nos simplificarán la vida.

Por ese motivo, me he visto animado a hacer una hoja o shortcut típica con la combinación de teclas más habituales y que nos sacarán de más de un aprieto o nos harán simplificar el acceso y ganar tiempo de forma extraordinaria.

La hoja con los atajos para Windows 8

Esta hoja en formato pdf, está basada en Windows 8 (Release Preview).

Es de esperar que no varíe mucho con respecto a la versión Windows 8 RTM final.

Podrás acceder a ella desde este enlace (490 Kb).

Pásasela a tus familiares y amigos, y ¡Que la disfrutes!.

Publicado por Jorge Serrano | con no comments
Archivado en:

Introducción

No soy persona de sangre caliente, pero la noticia de esta semana respecto a las novedades de Windows Phone 8 me hicieron dar un salto del asiento y aumentar las pulsaciones de mi corazón de forma drástica al mismo tiempo que sentía un calor que me recorría el cuerpo desde la punta de los pies hasta la cabeza.


Los cambios de rumbo de Microsoft

Estoy ya acostumbrado a los cambios (a veces espasmódicos) de Microsoft. En realidad y si me permite la comparación, los cambios de rumbo de Microsoft me recuerdan a la canción de "Follow the leader" donde en una sala de baile todos se ponen a bailar a las órdenes de alguien que hace de guía o líder.

Microsoft dice "left left", y todos a la izquierda,... y de repente dice "right right", y todos a la derecha... y todos coreando el mítico "follow the leader leader".

Reconozco que en el caso de Microsoft, muchos de esos cambios de rumbo han demostrado con el tiempo ser adecuados, incluso habiendo recibido feroces críticas al respecto, pero también ha habido fracasos como en todas las compañías (que tire la primera piedra la empresa que esté libre de pecado).


Windows Phone 7

Como usuario de Windows Mobile 6.5, que fue la última versión que tenía, me sentí decepcionado al ver que Microsoft se quedaba dormida y permitía que otras compañías la adelantaran.

Por poner un símil, me recuerda a la situación en la que el alumno de turno le dice a su madre que el profesor le tiene manía porque suspende todas las asignaturas y él hace todo lo posible. La madre va a hablar con el profesor y se da cuenta de que el problema es que el alumno no estudia lo suficiente o nada, por lo que no es una cuestión de que el profesor le tenga manía, sino de que el alumno, simplemente, no estudia.

En esta pequeña historia, el profesor sería el mercado, la madre los gerentes de Microsoft que piden resultados, y el estudiante, el equipo de desarrollo de Windows Mobile.

Apple se puso las pilas y Google contraatacó. Microsoft seguía pensando en que el profesor le tenía manía, y cuando se dió cuenta de que el problema era que simplemente no hacía los deberes ni estudiaba, ya era tarde. Había suspendido todas las asignaturas y debía repetir curso.

Empezó un nuevo curso y se puso a estudiar como loco y aunque no sacaba las máximas notas, sí que lograba ya aprobar el curso, raspadito pero lo hacía al fin y al cabo. Esto es lo que ocurrió con Windows Phone 7.0.

Nuestro alumno continuó esforzándose.
La diferencia con los otros alumnos, iPhone y Android, todavía era grande, pero el alumno siguiendo con ese esfuerzo, ha logrado en llegar a pasar del 5 al 6 ó 7... hablamos de Windows Phone 7.5.

Indudablemente, el mercado se siento más orgulloso de nuestro alumno que empieza a remontar el vuelo y sin llegar a ser aún un alumno aventajado, se ve más animado para lograr serlo.

Bien... y hasta aquí la historia completa de lo que ha sucedido hasta el momento.

¿Y Windows Phone 8?.


Windows Phone 8

Microsoft tiene ultimada la publicación de un nuevo sistema operativo, de nombre Windows 8.

Al mismo tiempo, Microsoft ha publicado una tableta desarrollada y fabricada enteramente por Microsoft y cuya marca es Surface. Esta tableta se venderá de dos formas, una basada en WinRT (Metro) y otra en Win32 (Windows 8 Pro).

La gracia de todo esto es que Microsoft quiere que Windows Phone 8 ejecute aplicaciones WinRT (Metro) en su entorno. Bueno en realidad, un subconjunto de WinRT que podría denominarse como Windows Phone RT o WinPhoneRT.

Utilizando el símil anterior, es como si nuestro alumno quisiera cursar una carrera en la Universidad y la nota media que llevara hasta ahora no le llegara, por lo que debería optar a sacar un 9 ó un 10 para lograr matricularse en la Universidad en la carrera que quiere hacer.

Así que para eso, Microsoft ha intentado ver como enlazar todos los puntos que están desconectados encima de la mesa.

Por un lado, se ha encontrado con que Windows Phone 7 está basado en WinCE (kernel del Windows Mobile y embrión del actual Windows Phone).

Metro está basado en WinRT y eso de WinCE como que es algo del pasado, así que aquí tenemos un problema y grande. O se hace un wrapper o nada... y hay cosas en WinCE que no están en WinRT, así que empezamos a tener problemas graves de incompatibilidad.

Por otro lado y a nivel de desarrollo, WinRT permite desarrollar aplicaciones con XAML, C#, VB, C++, DirectX... ¿Silverlight?... no... Silverlight no. ¡Vaya!,... ¡otro problema!.

Un poco más allá, tenemos un deseo lógico y apetecible, que consiste en la posibilidad de desarrollar una sóla aplicación para WinRT y que ésta valga para una tableta y un dispositivo móvil.
Con Windows Phone 7 y WinCE, esto... ¡vuelve a ser imposible!.

Si continuamos profundizando, observaremos algo muy interesante.
Microsoft que ha rozado la fragmentación con su maravillosa idea de cambiar los requisitos mínimos de Hardware para que los fabricantes diseñaran dos tipos de dispositivos móviles (uno caro y otro más asequible) para llegar a todas las personas... se ha dado cuenta de que... ¡la ha cagado! (y mira que lo dijimos muchos...).

Al mismo tiempo, si vamos a poder crear aplicaciones para una tableta y para un móvil, los requisitos Hardware van a variar y mucho, por lo no sólo será inservible el Hardware de los dispositivos "low-cost", sino que será necesario incrementar las características Hardware de los dispositivos "fetem".

En esa tesiruta, Microsoft ha pensado matar los dos problemas de un sólo tiro.

Microsoft ha pensado que si obliga a mejorar los requisitos Hardware de los dispositivos móviles que van a montar Windows Phone 8, se quita de en medio el comienzo de los problemas de la fragmentación que ellos mismos han generado.

Para no enfadar "demasiado" a los usuarios actuales, Microsoft va a hacer un refrito de Windows Phone, es decir, algunas de las mejoras de Windows Phone 8 las va a incluir en una actualización de Windows Phone 7.5 llamada Windows Phone 7.8.

En otras palabras. Windows Phone 7.5 se podrá actualizar a Windows Phone 7.8 y punto final.
Es una muerte anunciada.

Por lo tanto y siguiendo con la fábula anterior,... a nuestro alumno, lo han cambiado de colegio a uno diferente donde no conozcan su pasado de mal estudiante para que a la hora de calificarle nadie recuerde su turbio pasado y logre por méritos propios, una mejor nota, ya que si seguía en el mismo colegio corría el riesgo de estar encasillado debido a su pasado.


¿Cambios traumáticos?

Pues sí,... este cambio es un cambio traumático. Así de claro y cristalino.

Microsoft nos lo quiere vender como algo necesario, algo que no discuto porque efectivamente es tal y como dicen, necesario, pero ojo, necesario para sus intereses. Si obviamos Metro, Windows Phone seguiría avanzando por la misma senda, pero no es así, y por lo tanto, es y va a ser traumático para todos (usuarios, desarrolladores, fabricantes, mercado,...).

Las cosas son así, por mucho que algunos lo quieran disfrazar y por mucho que otros quieran permanecer callados sin criticar (constructivamente) lo que debe ser criticable, ya sea por miedo, por reputación o por lo que sea.

Respeto lo que cada uno quiera o no quiera decir en público, pero a veces es necesario poner los puntos sobre las íes, y este es uno de esos momentos.

Yo no creo que haya que asustarse por decir que el cambio es traumático y que encolerice a mucha gente, y tampoco hay que ocultar que el cambio sea al mismo tiempo positivo, no estrictamente necesario, pero sí necesariamente obligado por la existencia de Metro.

De hecho, y aunque aquí esté mostrando mi malestar, ya me he empezado a poner las pilas y a ponerme al día... de hecho, ya me he puesto a remar como titulaba en esta entrada, algo que aconsejo hacer al resto. Cuanto antes, mejor preparado se estará para abrazar, entender y comprender mejor el cambio.


Los daños colaterales

Y como en todos los cambios traumáticos, hay daños colaterales.

Aunque los he enumerado, me gustaría hablar de algunos de ellos.

Los usuarios:
Ser usuario de Windows Phone no es ni ha sido fácil.
Tengo una sensación muy negativa al respecto por parte de Microsoft, como si no hubiera entendido bien al mercado ni a sus usuarios y como si nos dejaran un poco tirados (y ojo, no es la primera vez).
Tuve un Pocket PC, dos o tres Windows Mobile, y después de ver que Microsoft se había quedado dormida en los laureles y esperar y esperar y esperar, me decanté por adquirir un Android.
Mi Android y su experiencia de usuario me encantaba y cuando Microsoft sacó su Windows Phone,... me costó cambiar. Lo reconozco, y eso que Microsoft como marca me gusta, pero me costó porque estaba bastante quemado con que Microsoft me hubiera dejado tirado.
Adquirí por fin y dubitativamente mi Windows Phone y cuando empecé a usarlo (un LG Optimus 7) me quedé prendado de él y de su experiencia de usuario, y pensé... "ni de broma regreso a Android".
Al final me hice con un Windows Phone Nokia Lumia 800, y la verdad es que estoy encantado con él.
Sin embargo, lo de esta semana me ha vuelto a recordar sentimientos que tenía ya olvidados... pensar que Microsoft vuelve a pegar otro volantazo y cambio drástico de rumbo a ritmo de la canción de "Follow the leader" dejándome sumido en una depresión una vez más.
A lo mejor soy el único usuario del mundo que piensa así,... pero honestamente lo dudo.
Me pongo en la piel de todos los usuarios que HAN VUELTO a confiar en Microsoft y aunque entiendo que los terminales móviles tienen todos ellos un ciclo de vida premeditamente corto, no deja de ser un fastidio saber que tu Windows Phone 7.5 se va a actualizar a Windows Phone 7.8 con algunas de las características que va a tener Windows Phone 8, y punto final de la historia... historia que parece repetirse... y es que uno como usuario se plantea una pregunta bochornosa al mismo tiempo que obligada... ¿va a Microsoft sacar dentro de un par de años un Windows Phone 9 dejando tirados nuevamente a los usuarios de Windows Phone 8?.
Lamento ser tan duro y drástico. Lo lamento de veras, pero es una pregunta obligada.

Los desarrolladores:
Ser desarrollador no es fácil.
Microsoft nos ha incitado a desarrollar para Windows Phone.
Algo lógico, porque sin aplicaciones en el mercado, es difícil que una plataforma tenga éxito.
No es un tiempo totalmente perdido el que hemos empleado los desarrolladores programando aplicaciones para Windows Phone, pero en parte sí.
Ahora nos enfrentamos a un nuevo paradigma de la programación denominado WinRT.
Apartando todo el contexto negativo que puede presentarse ante nosotros pensando en lo que hemos hecho por Windows Phone hasta ahora, es indudable que se abren oportunidades de negocio.
Entiendo que la comunidad de desarrolladores y las empresas de desarrollo, verán este asunto con una apariencia de amor/odio.
Es lo que es y Microsoft nos ha acostumbrado a ello desde hace tiempo.

Los fabricantes:
No sé como se lo habrán tomado los fabricantes.
Es de suponer que ya sabían algo desde hace meses, pero aún sabiéndolo, me pongo en la piel de Nokia y yo al menos, lo entendería como un torpedo lanzado a la línea de flotación de la empresa.
una empresa que ha puesto su ahínco y esfuerzo en promocionar Windows Phone y que se ha gastado una fortuna en anuncios, etc., ve como en un día, sus terminales pasar en un abrir y cerrar de ojos, de modernos a desfasados.
Igual no tengo ni idea de nada, pero mucho me temo que Microsoft ha abierto heridas y muchas.

El mercado:
El mercado valorará con el tiempo todo esto.
Lo que está claro es que ya empiezan a venderse terminales Nokia Lumia 800 y Nokia Lumia 900 a precios más bajos, y apenas han pasado 48 horas desde el anuncio.
En unos 6 meses tendremos los primeros terminales Windows Phone 8 en el mercado, y para cuando aparezcan, los Windows Phone 7 actuales, serán viejas glorias... una vez más.
Cuando tengamos todos terminales Windows Phone 8, nadie se acordará de esta entrada, pero en estos instantes, el mercado no está para grandes florituras.
Mucho me temo que habrá muchos usuarios que decidirán dejar de lado a Microsoft para irse a Android o iPhone, y muchos otros que estaban meditando el cambio y que ahora se lo pensará más. Otros (también me constan) tenían pensado adquirir un Windows Phone 7 y ahora esperarán a Windows Phone 8.
Mucho me temo que Microsoft ha tomado una decisión que se puede volver contra ellos, al menos en cuanto al mercado de móviles se refiere. Me temo que a Microsoft le va a costar mucho más de lo que tenía pensado con Windows Phone 7, obtener una cuota de mercado aceptable.
Tiempo al tiempo y ojalá esté equivocado...
Las características publicadas de Windows Phone 8 son espectaculares y es un móvil moderno, actual y capaz de hacer frente a cualquier dispositivo existente, bastante mejor que el actual Windows Phone 7, pero habrá que ver y valorar el daño que puede haber hecho este cambio drástico de Microsoft.


El futuro

El futuro está muy cerca.

Después del anuncio de Microsoft respecto a Windows Phone 8, en los próximos 6 meses calculo yo, empezaremos a escuchar rumores de terminales y posiblemente tengamos incluso en el mercado, los primeros terminales con Windows Phone 8.

Es posible que Windows Phone 8 ya esté prácticamente terminado y es posible que algún fabricante ya tenga disponible el primer terminal capaz de ejecutar Windows Phone 8, pero seguramente todo esto esté incluido dentro de un plan de desarrollo que en este momento esté en fase de pruebas.

De cara a los desarrolladores, lo inteligente es estar presto para poder dar el paso hacia adelante lo antes posible y sin muchos traumas.

Aquí Microsoft sí ha hecho las cosas MUY bien.

Ha puesto a disposición de muchísimas personas una versión preliminar de Windows 8 y una versión preliminar de las herramientas de desarrollo Visual Studio 2012.

No son versiones finales, pero a los desarrolladores nos permite empezar a trastear y estar preparados para crear aplicaciones Metro.

Aún queda tener en el entorno de desarrollo la posibilidad de crear aplicaciones Metro para Windows Phone 8, pero esto es algo que aparecerá en breve seguramente.

Lo mejor es que el paso de una aplicación Metro basada en WinRT a Metro basada en WinPhoneRT no debe ser extremadamente duro.


Conclusiones

Aunque soy crítico con la situación acaecida por parte de Microsoft con respecto a Windows Phone 7 y Windows Phone 8, soy optimista con respecto al futuro de Windows Phone 8, si bien creo que este cambio de rumbo le ha hecho mucho daño a Microsoft.

Algunos de los cambios de Windows Phone 8 eran más que necesarios y demandados por el mercado. Es quizás lo único que realmente salve o maquille un poco esta difícil toma de decisión, ya que entiendo y comprendo que la toma de esta decisión no ha debido de ser nada fácil porque Microsoft seguro que es consciente de lo que se juega.

También afirmo que delante nuestra se abre una gran cantidad de oportunidades con WinRT. Es cuestión de estar ahí preparados para saber adoptar y aprovechar estas oportunidades para sacar de ellas el máximo rendimiento.

Así que no nos queda otra... aunque sea con resignación,... ¡a remar!.

Más artículos < Página anterior - Página siguiente >