[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (5 de N)

Hola a todos!

En esta quinta entrega de la serie, tras haber visto como funcionan los contratos en las aplicaciones metro, vamos a profundizar un poco más con tres contratos muy útiles: buscar, compartir y configuración. Cada uno de estos contratos va a dar una gran funcionalidad a nuestra aplicación e integrarla con la forma de trabajar de Windows 8. Empecemos!

Search

El contrato de búsqueda permite que el usuario consulte a nuestra aplicación desde cualquier parte del sistema:

image

En esta pantalla, además de buscar aplicaciones, configuraciones o archivos, podemos buscar dentro de las propias aplicaciones listadas a la derecha. Si nuestra aplicación soporta el contrato de búsqueda vendrá listada aquí también.  Si por ejemplo escogemos la aplicación Weather y buscamos una ciudad, recibiremos resultados que podremos escoger:

image

¿Qué necesitamos para comenzar? En primer lugar, como recordaréis del último artículo, necesitamos indicar en las declaraciones de nuestra aplicación (package.appxmanifest) que deseamos soportar el contrato de búsqueda. Lo siguiente es que en nuestra clase App controlemos la activación mediante una búsqueda, con el método OnSearchActivated, lo que vamos a hacer en este caso es llamar a un método de nuestra página que recogerá el texto introducido por el usuario y lo mostrará en pantalla:

BlankPage.xaml.cs
  1. public void SetSearchQuery(string query)
  2. {
  3.     txtSearchQuery.Text = string.Format(«Search query:{0}», query);
  4. }

 

App.xaml.cs
  1. protected override void OnSearchActivated(SearchActivatedEventArgs args)
  2. {
  3.     base.OnSearchActivated(args);
  4.  
  5.     if (Window.Current.Content == null)
  6.     {
  7.         Window.Current.Content = new BlankPage();
  8.         Window.Current.Activate();
  9.     }
  10.  
  11.     ((BlankPage)Window.Current.Content).SetSearchQuery(args.QueryText);
  12. }

Si realizamos un despliegue de nuestra aplicación y a continuación abrimos la búsqueda de Windows, veremos que ya aparece listada y que al seleccionarla se activa y muestra el texto que hayamos indicado. Pero no hace mucho más, no nos ofrece sugerencias como la aplicación del tiempo… vamos a solucionar esto desde nuestra página BlankPage.xaml.

En primer lugar necesitamos añadir un using al namespace Windows.ApplicationModel.Search y a continuación crearemos dos variables privadas en nuestra clase, una será lista con distintas palabras y la otra almacenará la referencia al panel de búsqueda:

Variables
  1. private SearchPane searchPane;
  2. private List<string> list = new List<string>() { «prueba», «yeray», «julin», «Ferreiro», «Plain Concepts» };

Ahora, en el constructor vamos a obtener la instancia actual de la búsqueda y manejar el evento SuggestionsRequested que nos llegará cuando el usuario escriba en la caja de búsqueda:

Constructor
  1. public BlankPage()
  2. {
  3.     this.InitializeComponent();
  4.  
  5.     this.searchPane = SearchPane.GetForCurrentView();
  6.     this.searchPane.SuggestionsRequested += searchPane_SuggestionsRequested;
  7. }

De esta forma, cada vez que el usuario escriba en la caja de búsqueda, nos llegará la llamada al evento SuggestionsRequested y podremos obtener la consulta del usuario y añadir las sugerencias que coincidan (usando nuestro propio criterio de coincidencia) al panel de sugerencias:

SuggestionsRequested
  1. void searchPane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
  2. {
  3.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  4. }

También disponemos de más métodos para añadir solo una sugerencia o, por ejemplo, añadir un texto de separación usando el método AppendSearchSeparator:

AppendSearchSeparator
  1. void searchPane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
  2. {
  3.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  4.     args.Request.SearchSuggestionCollection.AppendSearchSeparator(«Another sugestions»);
  5.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  6. }

El resultado, podemos mostrar sugerencias, obtener las búsquedas y reaccionar de forma adecuada:

image

Share

El contrato de Share, compartir, nos permite intercambiar información entre aplicaciones. En Windows Phone 7.5 teníamos dos lanzadores, ShareStatusTask y ShareLinkTask, que nos permitían compartir texto o enlaces en las redes sociales configuradas en el sistema. En Windows 8 el contrato Share tiene un sentido mucho más amplio. Podemos hacer que nuestra aplicación sea una fuente de información y que otras aplicaciones puedan recoger esa información y usarla. De la misma forma podemos declarar que somos capaces e utilizar cierto tipo de información, de esa forma cuando alguna aplicación comparta, por ejemplo textos o imágenes, apareceremos en la lista de posibles destinos.

Esta operación de compartir información, como ya hemos comentado, consta de dos partes: la fuente de datos y el destino al que compartir. Veamos a continuación como implementar cada uno:

Share source

Nuestra aplicación puede contener información que el usuario quiera tratar, compartir, editar o modificar en otra aplicación. Por ejemplo, podemos tener una aplicación de Rss sobre noticias y el usuario puede tener una aplicación donde organiza todos los artículos que le parecen interesantes, podemos compartir las Urls de los artículos y que otras aplicaciones los recojan.

¿Como podemos hacerlo? Muy sencillo, lo primero que necesitamos es prepararnos para poder transferir datos, obteniendo una instancia de la clase DataTransferManager del namespace Windows.ApplicationModel.DataTransfer y manejando el evento DataRequested para cuando otra aplicación nos solicite datos:

DataTransferManager
  1. DataTransferManager datatransferManager;
  2. datatransferManager = DataTransferManager.GetForCurrentView();
  3. datatransferManager.DataRequested += datatransferManager_DataRequested;

A continuación vamos a crear la interface de usuario que nos permita compartir un texto introducido por el usuario:

XAML
  1. <Grid Background=»{StaticResource ApplicationPageBackgroundThemeBrush}«>
  2.     <Grid Margin=»110,20,20,20″>
  3.         <Grid.RowDefinitions>
  4.             <RowDefinition Height=»Auto»></RowDefinition>
  5.             <RowDefinition></RowDefinition>
  6.         </Grid.RowDefinitions>
  7.             
  8.         <TextBlock Text=»Windows 8 share source» FontSize=»36″></TextBlock>
  9.             
  10.         <StackPanel Grid.Row=»1″ Margin=»0,12,0,0″>
  11.             <TextBlock Text=»Texto a compartir» FontSize=»16″></TextBlock>
  12.             <TextBox Name=»txtText» Height=»100″ TextWrapping=»Wrap» AcceptsReturn=»True» Margin=»0,12,0,12″></TextBox>
  13.             <Button Content=»Compartir» Click=»Button_Click_1″></Button>
  14.         </StackPanel>
  15.     </Grid>
  16. </Grid>

En el evento del botón compartir mostramos la UI de compartir:

Button_click
  1. private void Button_Click_1(object sender, RoutedEventArgs e)
  2. {
  3.     DataTransferManager.ShowShareUI();
  4. }

Esto provocará que el sistema lance el evento DataRequested para identificar el tipo de datos que vamos a compartir y otras propiedades como el título y la descripción de la información que estamos compartiendo:

DataRequested
  1. void datatransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
  2. {
  3.     args.Request.Data.Properties.Title = «Compartiendo texto»;
  4.     args.Request.Data.Properties.Description = «Ejemplo de como usar el contrato Share»;
  5.     args.Request.Data.SetText(this.txtText.Text);
  6. }

Si ejecutamos nuestra aplicación, escribimos un texto y presionamos el botón compartir, aparecerá a la derecha una lista de las aplicaciones que pueden trabajar con la información que hemos expuesto:

image

Si a continuación seleccionamos la aplicación de correo, aparecerá directamente la vista de envío de un nuevo correo, con los datos que hemos indicado al compartir introducidos:

image

Como podemos observar es realmente sencillo usar la comunicación entre aplicaciones. Pero no solo podemos compartir texto, también podemos compartir imágenes o cualquier otro tipo de datos. Vamos a usar un FileOpenPicker, del namespace Windows.Storage.Pickers  para poder seleccionar una imagen de nuestro pc y compartirla:

Obtener una imágen
  1. FileOpenPicker imagePicker = new FileOpenPicker
  2. {
  3.     ViewMode = PickerViewMode.Thumbnail,
  4.     SuggestedStartLocation = PickerLocationId.PicturesLibrary,
  5.     FileTypeFilter = { «.jpg», «.png», «.bmp», «.gif», «.tif» }
  6. };
  7.  
  8. this.imageFile = await imagePicker.PickSingleFileAsync();

En el evento DataRequested podemos usar el método SetBitmap para establecer la imagen a compartir:

SetBitmap
  1. args.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(this.imageFile));

Pero la aplicación de correo no es capaz de compartir imágenes, por lo que no aparecerá ninguna aplicación disponible, no hay problema, vamos a ver como podemos crear una aplicación que pueda recibir imágenes o texto de forma indistinta.

Share target

Ahora que ya sabemos como hacer que nuestra aplicación se comunique con el resto del sistema usando las capacidades de compartir, veamos como podemos recibir información de otras aplicaciones, exponiéndonos como destino de los datos. Lo primero que necesitamos hacer es añadir a nuestra aplicación el contrato de Share Target y los tipos de datos que soportamos, editando la configuración del archivo Package.appxmanifest en este caso usaremos los tipos de datos de texto e imágenes:

image

Una vez añadidos estos tipos de datos que deseamos soportar, vamos a editar nuestro archivo App.xaml.cs para que soporte la activación de nuestra aplicación mediante el contrato Share, la entrada se realizará por el método OnShareTargetActivated:

OnShareTargetActivated
  1. protected async override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
  2. {
  3.     BlankPage shareTargetPage = new BlankPage();
  4.     await shareTargetPage.ShowData(args);
  5. }

Lo que hemos hecho es cargar nuestra página principal, aunque podría ser una página especial para cuando recibamos datos a compartir, y llamar a un método de esta página que hemos creado y será el encargado de cargar y mostrar todos los datos recibidos, el método ShowData:

ShowData
  1. public async Task ShowData(ShareTargetActivatedEventArgs args)
  2. {
  3.     txtApp.Text = args.ShareOperation.Data.Properties.ApplicationName;
  4.     txtTitle.Text = args.ShareOperation.Data.Properties.Title;
  5.     txtDescription.Text = args.ShareOperation.Data.Properties.Description;
  6.     txtText.Text = await args.ShareOperation.Data.GetTextAsync();
  7.  
  8.     IRandomAccessStreamReference imageReceived = await args.ShareOperation.Data.GetBitmapAsync();
  9.     IRandomAccessStreamWithContentType stream = await imageReceived.OpenReadAsync();
  10.     BitmapImage bitmapImage = new BitmapImage();
  11.     bitmapImage.SetSource(stream);
  12.     img.Source = bitmapImage;
  13.  
  14.     Window.Current.Content = this;
  15.     Window.Current.Activate();
  16. }

Igual que al compartir usamos los métodos SetBitmap y SetText, ahora usamos sus homónimos GetTextAsync y GetBitmapAsync, lo que nos permite obtener la imagen seleccionada por el usuario en la otra aplicación y el texto que escribió y mostrarlo en pantalla:

image

Como podemos ver, es realmente sencillo comunicar aplicaciones entre sí usando el contrato Share, además mantenemos nuestras aplicaciones independientes, pues lo único que necesitamos exponer es el tipo de datos que soportamos, nada más.

Settings

Por regla general, todas las aplicaciones tienen alguna opción que configurar, siempre hemos tenido que crear una pantalla de configuración para permitir al usuario personalizar su experiencia. En Windows 8 podemos integrar este trabajo con la barra de charms, teniendo las configuraciones de nuestra aplicación en el mismo sitio que los settings del sistema. Por defecto, automáticamente tendremos una sección de permisos, donde el usuario podrá habilitar o deshabilitar las capacidades otorgadas a nuestra aplicación. Por ejemplo, si requerimos acceso al micrófono o la localización:

image

De esta forma nos ahorramos pantallas especiales, enlaces y demás, el propio sistema se encarga de todo y además el usuario sabe donde encontrar la configuración de nuestra aplicación en cualquier momento. Además de esto, que se realiza de forma automática, podemos crear nuestras propias secciones con su contenido personalizado e integrarlo en el mismo menú de settings.

Lo que vamos a hacer es registrar nuevos botones al lanzar nuestra aplicación, en primer lugar tenemos que obtener una referencia al panel de settings actual, usando el tipo SettingsPane del namespace Windows.UI.ApplicationSettings:

SettingsPane
  1. private async Task RegisterSettings()
  2. {
  3.     SettingsPane settings = SettingsPane.GetForCurrentView();
  4.     settings.CommandsRequested += settings_CommandsRequested;
  5. }

A continuación en el evento CommandsRequested vamos a crear nuestros comandos y agregarlos a la barra de settings:

CommandsRequested
  1. void settings_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
  2. {
  3.     SettingsCommand HelpCommand = new SettingsCommand(«helpSetting», «Help», new UICommandInvokedHandler(onHelpCommand));
  4.     args.Request.ApplicationCommands.Add(HelpCommand);
  5.     SettingsCommand VideoCommand = new SettingsCommand(«videoSettings», «Video», new UICommandInvokedHandler(onVideoCommand));
  6.     args.Request.ApplicationCommands.Add(VideoCommand);
  7. }

Para cada comando además definimos un método que ejecutará al seleccionarlo:

Código comandos
  1. public async void onHelpCommand(IUICommand command)
  2. {
  3.     SettingsCommand HelpCommand = (SettingsCommand)command;
  4.     MessageDialog dlg = new MessageDialog(«Has seleccionado Help»);
  5.     await dlg.ShowAsync();
  6. }
  7.  
  8. public async void onVideoCommand(IUICommand command)
  9. {
  10.     SettingsCommand VideoCommand = (SettingsCommand)command;
  11.     MessageDialog dlg = new MessageDialog(«Has seleccionado Video»);
  12.     await dlg.ShowAsync();
  13. }

Si ejecutamos nuestra aplicación, veremos las nuevas secciones y al seleccionar una se nos mostrará el texto indicado:

image

De esta forma podemos permitir que el usuario acceda a la configuración de nuestra aplicación desde un punto unificado.

Conclusión

Con esto, hemos terminado nuestro repaso a los contratos de Windows 8, hay muchos más, pero creo que habiendo visto en profundidad los contratos de busqueda, compartir y settings, el resto no nos darán problemas. Como siempre, os dejo los proyectos con el código completo de los ejemplos que hemos visto, podéis descargarlos aquí. Espero veros a todos en próximos artículos.

Un saludo y Happy Coding!

[MATERIALES] Evento AppCircus Sevilla Windows Phone 7.5

AppCircus Sevilla

Hola a todos!

El pasado jueves 19 de Abril estuve en tierras sevillanas impartiendo un workshop de introducción al desarrollo en Windows Phone 7.5 junto a Oscar Gutiérrez de Nokia Spain. Dimos un repaso a que es metro, MVVM, pruebas unitarias y desarrollamos una aplicación funcional para a continuación ver como usar herramientas como el Marketplace test kit y como subirla al App hub de Windows Phone.

Aquí os dejo el código de ejemplo de la aplicación que desarrollamos y a continuación las slides de la presentación:

Un saludo y Happy Coding!

[EVENTO] Windows Phone 7.5 en AppCircus Sevilla

Hola a todos!

AppCircus Sevilla

Este jueves 19 de Abril se celebrará en la ETSI Informática de la Universidad de Sevilla una nueva edición del concurso AppCircus. En esta ocasión estaré junto a Oscar Gutierrez de Nokia Spain presentando un workshop de desarrollo sobre Windows Phone 7.5.

Daremos un repaso rápido sobre:

  • Que es Metro
  • Las herramientas de desarrollo
  • El patrón MVVM
  • El Marketplace de Windows Phone

Intentaremos desarrollaremos una aplicación completa y veremos como podemos subirla al marketplace.

Os espero a las 10:30 el 19 de Abril para hablar un poco sobre Windows Phone y su modelo de desarrollo, no os lo perdáis.

Un saludo y Happy Coding!

[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (4 de N)

Volvemos a la carga con un nuevo artículo de la serie!

En nuestro último artículo sobre el ciclo de vida de las aplicaciones Metro vimos como es posible activar nuestra aplicación en respuesta a un requerimiento del sistema (como una búsqueda) o a otras aplicaciones (presentándonos como objetivo para guardar archivos). Pero no profundizamos en como llevar a cabo estas tareas. En este artículo vamos a ver que son los contratos, como configurar nuestra aplicación para que indique que contratos soporta y como realizar comunicaciones entre aplicaciones.

Contratos

El concepto de contrato es nuevo en Windows 8, en Windows Phone 7.5 disponíamos de sistemas que nos permitía exponer nuestra aplicación como capaz de editar fotos mediante Picture extensibility o realizar búsquedas llamado App Connect. Los contratos obtienen esta idea y la extienden más allá, permitiendo nuevas formas de interacción.

Package.appxmanifest

Para que nuestra aplicación sea capaz de usar estas características, lo primero que tenemos que hacer es habilitar las que deseamos usar, esto lo conseguiremos haciendo doble click sobre el archivo Package.appxmanifest de nuestra solución, que nos permitirá configurar nuestra aplicación. Esta pantalla, se divide en cuatro secciones distintas: Application UI, Capabilities, Declarations y Packaging:

Application UI nos permite configurar detalles sobre la interface de usuario de nuestra aplicación: rotaciones soportadas, nombre, iconos, etc…

image

Capabilities sirve para indicar que capacidades del sistema puede usar nuestra aplicación, lo que en Windows Phone se configuraba manualmente en el archivo WMAppManifest.xml, ahora con una interface más agradable:

image

Es importante que tengamos en cuenta que estas capacidades indican a qué tendrá acceso nuestra aplicación, una vez instalada, si deseamos cambiar alguna capacidad tendremos que desinstalarla y volver a instalarla.

Packaging nos ofrece datos generales sobre el paquete que se genera al compilar nuestra aplicación, el nombre de paquete, logo, el certificado a usar:

image

Declarations, nos lo habíamos saltado para poder tratarlo en más profundidad, la pestaña Declarations nos permite establecer y configurar los contratos a los que responderá nuestra aplicación:

image

 

Un Ejemplo FileSavePicker

Podemos seleccionar un elemento de la lista de available declarations y añadirlo a las supported declarations, en ese momento nos pedirá toda la configuración que necesite para poder funcionar. Si por ejemplo añadimos el contrato File save picker veremos sus valores de configuración:

image

Podemos configurar el tipo de archivo soportado, indicando sus extensión o eliminar todos los tipos y marcar el checkbox de soportar cualquier tipo, caso en el cual nuestra aplicación aparecerá como destino para guardar en todas las demás aplicaciones Metro, como por ejemplo al guardar un PDF desde la aplicación Reader:

image

Como vimos en el capítulo anterior, cuando el usuario seleccione nuestra aplicación en la lista de destinos para guardar, se activará mediante el evento OnFileSavePickerActivated, donde podremos establecer la UX que queremos mostrar al usuario:

OnFileSavePickerActivated
  1. protected override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args)
  2. {
  3.     var page = new BlankPage();
  4.     page.Activate(args);
  5. }

Y en el método Activate de nuestra página, acceder al FileSavePickerActivatedEventArgs para obtener la información necesaria y mostrar la interface:

Activación de la página
  1. public void Activate(FileSavePickerActivatedEventArgs args)
  2. {
  3.     txtFile.Text = args.FileSavePickerUI.FileName;
  4. }

Si realizamos un Deploy de nuestra aplicación y a continuación abrimos un pdf por ejemplo, podremos ver los resultados. En la lista de opciones de guardar encontraremos nuestra aplicación.

¿Como saber cuando el usuario a presionado el botón guardar? Tenemos un evento en FileSavePickerActivatedEventArgs que nos indica exactamente esto: TargetFileRequested, en este evento podemos guardar el archivo donde deseemos:

Guardando un archivo
  1. async void FileSavePickerUI_TargetFileRequested(Windows.Storage.Pickers.Provider.FileSavePickerUI sender, Windows.Storage.Pickers.Provider.TargetFileRequestedEventArgs args)
  2. {
  3.     var deferral = args.Request.GetDeferral();
  4.  
  5.     args.Request.TargetFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(sender.FileName);
  6.  
  7.     deferral.Complete();
  8. }

Ya que la llamada es asíncrona, usamos un deferral para indicar a la aplicación Host cuando hemos terminado la operación mediante el método Complete(), siendo la aplicación host la encargada de mostrar la UX de espera al usuario:

image

Conclusión

En las aplicaciones Metro los contratos nos permitirán expandir nuestras aplicaciones mucho más allá de su interface de usuario, con lo que podremos crear nuevas formas de interactuar con el usuario y sus datos. En próximos capítulo veremos nuevos contratos como el de compartir o el de búsqueda y que implicaciones tenemos que tener en cuenta a la hora de usarlos. Como siempre, aquí tenéis el código de ejemplo del artículo de hoy, espero que haya sido de interés y ayuda.

Un saludo y Happy Coding!

[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (3 de N)

Hola a todos!

En los artículos anteriores de la serie, hemos visto los fundamentos básicos para usar MVVM en una aplicación Metro: ViewModel Base, ViewModel Locator y Navegación. Hoy vamos a ver las particularidades del ciclo de vida de una aplicación Metro y lo parecido que este ciclo es al que tenemos en Windows Phone 7.5.

Ciclos de vida: Windows 8 vs Windows Phone 7.5

image

Como podemos observar en la comparación anterior, ambos sistemas comparten la misma base en su ciclo de vida: Una aplicación entra en ejecución, se suspende por una acción del usuario (cambio a otra aplicación, terminación, un fallo…) y una vez suspendida puede volver a entrar en ejecución por que el usuario la recupere o quedar indefinidamente en este estado hasta que el sistema decida terminarla por necesidades de rendimiento o cualquier otra consideración.

Sin embargo, si vemos los diagramas, Windows 8 parece ofrecer un ciclo de vida más simple (lo que no significa que sea menos potente o nos de menos opciones). Además, como añadido en Windows 8 la activación de nuestra aplicación puede venir dada por varios caminos, como veremos a continuación.

Estado: Activación

En Windows Phone nuestra aplicación podía ser Activada generalmente por dos vías: El usuario la lanzaba desde el tile de aplicación o volvíamos a ejecución después de estar en suspensión o en tombstoning.

En Windows 8, si el usuario lanza nuestra aplicación desde el tile de la misma o desde un tile de contenido (secundario), recibiremos el evento OnLaunched, situado en nuestro archivo app.xaml.cs:

Application OnLaunched
  1. protected override void OnLaunched(LaunchActivatedEventArgs args)
  2. {
  3.     // Create a Frame to act navigation context and navigate to the first page
  4.     var rootFrame = new Frame();
  5.     rootFrame.Navigate(typeof(BlankPage));
  6.  
  7.     // Place the frame in the current Window and ensure that it is active
  8.     Window.Current.Content = rootFrame;
  9.     Window.Current.Activate();
  10. }

Dentro de este evento se crea el Frame principal de nuestra aplicación, navegamos a nuestra página inicial y activamos la ventana principal. Además en el parámetro LaunchActivatedEventArgs podremos comprobar cual fue el estado anterior de ejecución de nuestra aplicación, de esta forma podemos comportarnos de diferente forma dependiendo de si la aplicación fue suspendida, terminada, cerrada por el usuario… todo esto a partir del enumerador ApplicationExecutionState:

Enum ApplicationExecutionState
  1. switch (args.PreviousExecutionState)
  2. {
  3.     case ApplicationExecutionState.ClosedByUser:
  4.     {
  5.  
  6.         break;
  7.     }
  8.     case ApplicationExecutionState.NotRunning:
  9.     {
  10.         break;
  11.     }
  12.     case ApplicationExecutionState.Running:
  13.     {
  14.         break;
  15.     }
  16.     case ApplicationExecutionState.Suspended:
  17.     {
  18.         break;
  19.     }
  20.     case ApplicationExecutionState.Terminated:
  21.     {
  22.         break;
  23.     }
  24. }

Pero Windows 8 ofrece nuevas formas de lanzar nuestra aplicación. Podemos responder a otros tipos de activación. Por poner un ejemplo, podemos indicar que el usuario puede buscar datos en nuestra aplicación, gestionar archivos y algunas otras opciones. Para estos casos especiales disponemos de Métodos de activación independientes que nos permitirán ejecutar la lógica necesaria:

Método Responde a…
OnSearchActivated Se lanza cuando la aplicación es iniciada desde la búsqueda del sistema operativo.
OnFileActivated Cuando se abre un archivo para cuyo tipo nos hemos registrado como que podemos abrirlo.
OnFileSavePickerActivated Si otra aplicación quiere guardar un archivo que podemos manejar, el usuario podrá escoger nuestra aplicación como destino y recibiremos este evento
OnFileOpenPickerActivated Al igual que al guardar, también podemos indicar que pueden abrir archivos de nuestra aplicación y nos llamarán a través de este evento.
OnShareTargetActivated Si nuestra aplicación es capaz de compartir información a redes sociales, el usuario puede usarla desde otras aplicaciones y recibiremos este evento

En el código del App.xaml.cs podremos manejar el evento o eventos que deseemos:

Eventos de activaci&amp;amp;amp;#243;n
  1. protected override void OnSearchActivated(SearchActivatedEventArgs args)
  2. {
  3.     base.OnSearchActivated(args);
  4. }
  5.  
  6. protected override void OnFileActivated(FileActivatedEventArgs args)
  7. {
  8.     base.OnFileActivated(args);
  9. }
  10.  
  11. protected override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args)
  12. {
  13.     base.OnFileSavePickerActivated(args);
  14. }
  15.  
  16. protected override void OnFileOpenPickerActivated(FileOpenPickerActivatedEventArgs args)
  17. {
  18.     base.OnFileOpenPickerActivated(args);
  19. }
  20.  
  21. protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
  22. {
  23.     base.OnShareTargetActivated(args);
  24. }

En próximos artículos veremos como activar cada una de estas actividades y como responder a ellas. Ahora lo importante es saber que estos son posibles puntos de entrada a nuestra aplicación.

Forzar Suspensión y Reinicio

Antes de pasar a ver como trabajar con los eventos de Suspensión y Reinicio, es importante que sepamos como forzar su ejecución. En Visual Studio 11 Beta debemos mostrar la barra de Debug Location (View > Toolbars > Debug Location) donde tendremos botones específicos para Suspender y reiniciar nuestra aplicación:

Estado: Suspensión

De forma muy parecida a Windows Phone, el estado de suspensión de una aplicación en Windows 8 se establece siempre que la aplicación no está viéndose en pantalla. Cuando esto ocurra, podemos tener una oportunidad de preservar información manejando el evento Suspending de la clase App:

Evento Suspending
  1. public App()
  2. {
  3.     this.InitializeComponent();
  4.     App.Current.Suspending += OnSuspending;
  5. }

Una vez que recibamos la llamada al método que maneja el evento Suspending, dispondremos de un máximo de 5 segundos (tiempo de procesador, no real) para guardar nuestros datos de forma segura:

Manejador OnSuspending
  1. void OnSuspending(object sender, SuspendingEventArgs e)
  2. {
  3.     KeyValuePair<string, object> data = new KeyValuePair<string,object>(«Nombre», «yeray»);
  4.     if (!ApplicationData.Current.LocalSettings.Values.Contains(data))
  5.         ApplicationData.Current.LocalSettings.Values.Add(data);
  6. }

Dentro del parámetro SuspendingEventArgs podemos encontrar una propiedad llamada SuspendingOperation que contiene toda la información sobre la suspensión que se está llevando a cabo. Una propiedad interesante es la Deadline que nos indica la fecha / hora exacta en la que termina el tiempo que tenemos para guardar los datos.

Dentro de esta propiedad SuspendingOperation tenemos un método GetDeferral que nos permite obtener un objeto del tipo SuspendingDeferral, una vez obtenido podemos ejecutar nuestro código de guardado y llamar al método Completed de SuspendingDeferral para indicar al sistema que hemos terminado y puede continuar con la suspensión. Esto no evita que debamos cumplir con el Deadline indicado en SuspendingOperation:

Uso de GetDeferral()
  1. void OnSuspending(object sender, SuspendingEventArgs e)
  2. {
  3.     SuspendingDeferral def = e.SuspendingOperation.GetDeferral();
  4.  
  5.     KeyValuePair<string, object> data = new KeyValuePair<string,object>(«Nombre», «yeray»);
  6.     if (!ApplicationData.Current.LocalSettings.Values.Contains(data))
  7.         ApplicationData.Current.LocalSettings.Values.Add(data);
  8.  
  9.     def.Complete();
  10. }

 

NOTA: Además de todo esto hay algo más que debemos tener en cuenta: Windows 8 administrará su memoria para tener el mayor número de aplicaciones en suspensión posible, pero si necesita liberar memoria empezará por las aplicaciones que más gasten, sin tener en cuenta la antigüedad de las aplicaciones en suspensión, por esto es buena idea que intentemos guardar en el almacenamiento todo lo que podamos e intentar que nuestra aplicación en suspensión sea lo más liviana posible, para tener más oportunidades de permanecer en suspensión.

Visibilidad

Aunque no se trata de un estado de la aplicación, sí es una parte importante de su ciclo de vida. En Windows Phone una vez que el usuario sale de nuestra aplicación por cualquier motivo (sin cerrarla) recibimos de manera automática el evento Deactivated que correspondería al evento Suspending de Windows 8. Pero en Windows 8 esta operación puede tener un retraso de hasta 10 segundos, tiempo durante el cual nuestra aplicación sigue en ejecución aunque no esté visible. Si volvemos a nuestra aplicación durante este tiempo, no se llevará a cabo la suspensión y reinicio de la aplicación, en su lugar solo se cambiará la propiedad Visibility de la ventana principal.

Podemos controlar estos cambios de visibilidad manejando el evento VisibilityChanged de nuestra ventana principal, justo después de activarla (como podemos ver en la línea tres del siguiente código):

Manjeando VisibilityChanged
  1. Window.Current.Content = rootFrame;
  2. Window.Current.Activate();
  3. Window.Current.VisibilityChanged += Current_VisibilityChanged;

Una vez recibido el evento podemos realizar acciones dependiendo de si estamos ocultándonos o volviendo a ser visibles:

Manejador VisibilityChanged
  1. void Current_VisibilityChanged(object sender, Windows.UI.Core.VisibilityChangedEventArgs e)
  2. {
  3.     if (e.Visible)
  4.         Text = «Application visible»;
  5.     else
  6.         Text = «Application hidden»;
  7. }

Estado: Reinicio

Una vez que nuestra aplicación esté suspendida pueden ocurrir dos cosas: que el usuario vuelva a activarla en algún momento o que, por necesidades del sistema, Windows 8 la termine y elimine completamente de memoria. En el primer caso, recibiremos el evento Resuming al que podemos subscribirnos para realizar acciones adicionales necesarias para volver a poner en funcionamiento nuestra aplicación:

Registro de eventos
  1. public App()
  2. {
  3.     this.InitializeComponent();
  4.     App.Current.Suspending += OnSuspending;
  5.     App.Current.Resuming += OnResuming;
  6. }

Una vez subscritos al evento, podremos cargar valores que hayamos guardado en el ApplicationData durante el evento Suspending:

Manejador OnResuming
  1. void OnResuming(object sender, object e)
  2. {
  3.     Text = ApplicationData.Current.LocalSettings.Values[«Nombre»].ToString();
  4. }

LocalSettings vs RoamingSettings

Antes de continuar con el último de los estados posibles, quiero dedicarle un poco de atención a unas propiedades nuevas y extremadamente interesantes de la clase ApplicationData en Windows 8: LocalSettings y RoamingSettings. Estas dos propiedades tienen el mismo funcionamiento exacto:

RoamingSettings
  1. ApplicationData.Current.RoamingSettings.Values.Add(data);
  2. Text = ApplicationData.Current.RoamingSettings.Values[«Nombre»].ToString();

¿Cual es su diferencia? Pues básicamente LocalSettings guarda la información en el dispositivo que estemos usando, mientras que RoamingSettings la almacena en la nube y su contenido será accesible por nuestra aplicación en otros dispositivos que usen el mismo LiveID que estamos usando en este. Con esta pequeña diferencia, podremos realizar aplicaciones que se sincronicen entre varios dispositivos.

Podemos subscribirnos al Evento DataChanged de la clase ApplicationData (línea 7) para que se nos notifique cuando los datos en roaming han cambiado y así obtener los nuevos valores:

Evento DataChanged
  1. public App()
  2. {
  3.     this.InitializeComponent();
  4.     App.Current.Suspending += OnSuspending;
  5.     App.Current.Resuming += OnResuming;
  6.  
  7.     ApplicationData.Current.DataChanged += Current_DataChanged;
  8. }
  9.  
  10. void Current_DataChanged(ApplicationData sender, object args)
  11. {
  12.     Text = sender.RoamingSettings.Values[«Nombre»].ToString();
  13. }

Ejemplo

Para terminar este artículo he creado un ejemplo que va añadiendo los distintos estados por los que transita a una colección y mostrando esta colección en una lista en pantalla para que podamos comprobar como afectan nuestras acciones al ciclo de vida de la aplicación:

image

 

Conclusión

Con este artículo hemos visto todo lo que el ciclo de vida de una aplicación Metro tiene que ofrecer y como se parece y se diferencia de lo aprendido en Windows Phone, aunque son muy parecidos, se aprecia el trabajo de Microsoft en darnos un ciclo de vida más potente y la capacidad de realizar Roaming de los datos de nuestra aplicación podrá marcar la diferencia… Ahora solo necesitamos que Windows Phone lo soporte también, para poder realizar aplicaciones en ambas plataformas que se sincronicen entre sí, teniendo una versión tablet  y una versión móvil que nos permitan interactuar sobre la misma información de maneras distintas. Como siempre os dejo el código del ejemplo aquí para que podáis jugar con el, nos vemos en el próximo artículo de la serie.

Un saludo y Happy Coding!

[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (2 de N)

Hola a todos!

En el primer artículo de esta serie pudimos ver como la implementación del patrón MVVM no había sufrido demasiadas variaciones y también como el apartado de Navegación había variado notablemente. Hoy quiero dedicar este segundo artículo de la serie a los mecanismos a usar para conectar nuestras Views con sus respectivas ViewModels.

Enlazando Views y ViewModels

Tras ver como podíamos usar el patrón MVVM perfectamente en una aplicación Windows 8 Metro, quiero explorar las opciones que tenemos para “casar” nuestra View con su ViewModel correspondiente, de la forma más limpia y organizada que sea posible. Para empezar, vamos a ver como lo haríamos en Windows Phone 7.5:

En Windows Phone 7.5 el enlace entre View y ViewModel lo haríamos a través de 3 pasos fundamentales. En primer lugar podríamos usar IoC para tener un mecanismo que resuelva nuestras ViewModels a partir de su Interface. Tras esto, podríamos usar una clase Locator que se encargaría de exponer propiedades, una por cada ViewModel, para que finalmente podamos asignar mediante enlaces de datos estas propiedades al DataContext de nuestra View. El proceso seguiría el siguiente esquema:

image

La ventaja de esta forma de trabajar es que obtenemos un único punto donde se resuelve la ViewModel a usar para cada View, además, al trabajar centrándonos en Interfaces para resolverlas podemos cambiar la implementación de forma sencilla y sin afectar a la View.

En una aplicación Metro, los pasos son casi idénticos, la mayor diferencia con Windows Phone es que, debido a que la plataforma es muy nueva, no existen todavía implementaciones de los IoC más usados como puede ser Unity o NInject por lo que esta parte, al menos por ahora deberemos resolverlo de otra forma. Salvo esto, el resto de pasos son iguales.

Para nuestro ejemplo crearemos un nuevo proyecto de C# + XAML en blanco (Windows Metro Style > Blank Application). Vamos a tener una ViewModel muy sencilla que herede de una clase base donde se implemente el interface INotifyPropertyChanged (como ya vimos en el artículo anterior) y que simplemente exponga una propiedad HelloMessage:

ViewModel VMStartPage
  1. public class VMStartPage : VMBase
  2. {
  3.     public VMStartPage()
  4.     {
  5.         HelloMessage = «Hi! Windows 8»;
  6.  
  7.         RaiseChange(«HelloMessage»);
  8.     }
  9.  
  10.     public String HelloMessage { get; set; }
  11. }

Como podemos ver es muy sencilla, también tendremos una página inicial que mostrará la cadena de texto de HelloMessage en el centro de la pantalla:

Pagina BlankPage.xaml
  1. <Page
  2.     x:Class=»Win8MetroMVVM.BlankPage»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:local=»using:Win8MetroMVVM»
  6.     xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
  7.     xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
  8.     mc:Ignorable=»d»>
  9.  
  10.     <Grid Background=»{StaticResource ApplicationPageBackgroundThemeBrush}«>
  11.         <TextBlock Text=»{Binding HelloMessage}« FontSize=»122″ Foreground=»White»
  12.                    VerticalAlignment=»Center» HorizontalAlignment=»Center»>
  13.         </TextBlock>
  14.     </Grid>
  15. </Page>
 

Como se puede apreciar, hemos indicado en la propiedad Text del textblock que use la propiedad HelloMessage de nuestra ViewModel, pero no le hemos dicho cual es la ViewModel que deseamos usar, eso a continuación!

Implementar ViewModelLocator

Una vez que tenemos nuestra View y su ViewModel creadas, vamos a crear un Locator, esta clase será la encargada de exponer la instancia de nuestra ViewModel cada vez que la View la necesite. Realizaremos esto usando por un lado una variable privada del tipo Lazy<T> y una propiedad pública del tipo de nuestra ViewModel, de esta forma la primera vez que se pida la ViewModel se creará y en consecuentes peticiones ya tendremos creada nuestra instancia:

Clase ViewModelLocator
  1. public class ViewModelLocator
  2. {
  3.     Lazy<VMStartPage> startPage;
  4.  
  5.     public ViewModelLocator()
  6.     {
  7.         startPage = new Lazy<VMStartPage>(() => { return new VMStartPage(); });
  8.     }
  9.  
  10.     /// <summary>
  11.     /// Returns the active instance of startPage viewmodel
  12.     /// </summary>
  13.     public VMStartPage StartPage
  14.     {
  15.         get
  16.         {
  17.             return startPage.Value;
  18.         }
  19.     }
  20. }

Como podemos ver es una clase muy sencilla. Ahora solo tenemos que acabar de atar todos los cabos, vamos a por el enlace a datos!

Realizar los Bindings

En primer lugar vamos a compilar nuestra aplicación (sin ejecutar) y abrimos el archivo App.xaml, donde vamos a añadir una referencia al namespace de nuestro ViewModelLocator (línea 5) y un nuevo recurso que sea el propio ViewModelLocator (línea 11):

App.xaml
  1. <Application
  2.     x:Class=»Win8MetroMVVM.App»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:vmLocator=»using:Win8MetroMVVM.ViewModels»
  6.     xmlns:local=»using:Win8MetroMVVM»>
  7.  
  8.     <Application.Resources>
  9.         <ResourceDictionary>
  10.             
  11.             <vmLocator:ViewModelLocator x:Key=»Locator»></vmLocator:ViewModelLocator>
  12.             
  13.             <ResourceDictionary.MergedDictionaries>
  14.                 <ResourceDictionary Source=»Common/StandardStyles.xaml»/>
  15.             </ResourceDictionary.MergedDictionaries>
  16.  
  17.         </ResourceDictionary>
  18.     </Application.Resources>
  19. </Application>

Ahora podemos ir a nuestra página BlankPage.xaml y añadir a la definición de la página la propiedad DataContext, enlazada a nuestro nuevo recurso Locator:

Cabecera BlankPage.xaml
  1. <Page
  2.     x:Class=»Win8MetroMVVM.BlankPage»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:local=»using:Win8MetroMVVM»
  6.     xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
  7.     xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
  8.     mc:Ignorable=»d»
  9.     DataContext=»{Binding StartPage, Source={StaticResource Locator}}«>

Si hemos seguido todos los pasos correctamente, podremos ejecutar la aplicación y veremos un resultado que debería parecerse a este:

image

BONUS: Lo mejor de todo es que hemos realizado todo esto y tenemos nuestra ViewModel funcionando sin escribir ni una sola línea de Code Behind!!

Conclusión

Con lo visto en estos dos primeros artículos de la serie, ya podemos empezar a plantear nuestras aplicaciones Metro, usando MVVM, resolviendo nuestras ViewModel con una clase Locator y realizando enlace a datos. Como de costumbre, aquí os dejo el proyecto de ejemplo para que podáis jugar con el hasta el próximo artículo!

Un saludo y Happy Coding!

[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (1 de N)

Hola a todos!

Hoy vamos a cambiar un poco la temática del blog, para hablar de Windows 8 y más concretamente de las aplicaciones Metro. Vamos a dar un vistazo a las similitudes y diferencias que encontraremos en este tipo de aplicaciones desde el punto de vista de un desarrollador Windows Phone.

Una de las cosas que nos sorprenderá cuando empecemos a trabajar con Windows 8 y sus aplicaciones Metro, será el gran número de similitudes que encontraremos con la plataforma Windows Phone. Aunque sutiles, también encontraremos diferencias en el desarrollo, pero son fáciles de comprender y acostumbrarnos a ellas es más fácil todavía. Vamos a comenzar por los cimientos.

Unos buenos cimientos: MVVM

Una de las cosas que no ha cambiado en Windows 8 es la forma de aplicar el patrón MVVM en nuestra aplicación. Podemos coger la estructura de una aplicación Windows Phone y trasladarla fácilmente a Windows 8. Las expresiones de enlace a datos siguen funcionando como siempre lo han  hecho y podemos establecer nuestra ViewModel como DataContext de una página.

En Windows Phone es muy normal usar una viewmodel base, que implemente INotifyPropertyChanged y para las colecciones apoyarnos en ObservableCollection<T>.

En la versión developer preview de Win8 esto nos podía dar algún dolor de cabeza (mira este artículo de Eduard Tomas) pues existían dos implementaciones de INotifyPropertyChanged: la de siempre, que se encuentra en System.ComponentModel y la nueva implementación en WinRT que se encontraba en Windows.UI.Xaml.Data Esto hacía que los cambios no se notificasen correctamente. Pero parece que en la nueva versión Consumer preview se han unificado de nuevo, manteniéndose en System.ComponentModel, y desapareciendo de Windows.UI.Xaml.Data.

De esta forma, podemos crear una ViewModel base realmente sencilla y totalmente intercambiable entre Windows Phone y Windows 8:

VMBase
  1. using System.ComponentModel;
  2.  
  3. namespace Geeks.ms.ViewModels.Base
  4. {
  5.     public class VMBase : INotifyPropertyChanged
  6.     {
  7.         public VMBase()
  8.         {
  9.         }
  10.  
  11.         public event PropertyChangedEventHandler PropertyChanged;
  12.  
  13.         public void RaiseChange(string name)
  14.         {
  15.             if (PropertyChanged != null)
  16.                 PropertyChanged(this, new PropertyChangedEventArgs(name));
  17.         }
  18.     }
  19. }

Navegación

El mayor cambio que encontraremos al implementar MVVM se centrará fundamentalmente en la forma de navegar entre las páginas de nuestra aplicación. En Windows Phone, una clase normal de navegación que pudiese ser usada desde cualquier ViewModel simplemente tenía que obtener el contener principal de la aplicación, expuesto a través de la propiedad RootVisual del objeto App:

Navegación en Windows Phone
  1. public void NavigateTo(String navigationTarget)
  2. {
  3.     PhoneApplicationFrame rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
  4.     rootFrame.Navigate(registeredViews[navigationTarget]);
  5. }

En Windows 8 no disponemos de la propiedad RootVisual. Al inicializar la aplicación se crea un objeto Frame que es el encargado de gestionar la navegación. Lo que necesitamos para poder crear un servicio de navegación básico es crear una propiedad estática en nuestra clase App que nos devuelva este Frame principal:

RootFrame
  1. sealed partial class App : Application
  2. {
  3.     /// <summary>
  4.     /// Application main frame, used for navigation
  5.     /// </summary>
  6.     public static Frame RootFrame = new Frame();

En el evento OnLaunched usaremos este RootFrame para navegar a nuestra página inicial y lo estableceremos como el contenido de nuestra ventana:

Evento OnLaunched
  1. protected override void OnLaunched(LaunchActivatedEventArgs args)
  2. {
  3.     if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
  4.     {
  5.     }
  6.  
  7.     // Create a Frame to act navigation context and navigate to the first page
  8.  
  9.     RootFrame.Navigate(typeof(BlankPage));
  10.  
  11.     // Place the frame in the current Window and ensure that it is active
  12.     Window.Current.Content = RootFrame;
  13.     Window.Current.Activate();
  14. }

Ahora solo nos queda obtener una referencia a este Frame principal en nuestra clase de navegación y usarlo en nuestros métodos:

Clase NavigationService
  1. using System;
  2. using Geeks.ms.Views;
  3. using Windows.UI.Xaml.Controls;
  4.  
  5. namespace Geeks.ms.Services.Navigation
  6. {
  7.     public class NavigationService : INavigationService
  8.     {
  9.         private readonly Frame frame;
  10.  
  11.         public NavigationService()
  12.         {
  13.             frame = App.RootFrame;
  14.         }
  15.  
  16.         public void NavigateBack()
  17.         {
  18.             frame.GoBack();
  19.         }
  20.  
  21.         public bool CanNavigateBack()
  22.         {
  23.             return frame.CanGoBack;
  24.         }
  25.  
  26.         public void NavigateToArticle(Uri articleUri)
  27.         {
  28.             frame.Navigate(typeof(VArticle), articleUri);
  29.         }
  30.     }
  31. }

Y ya podremos invocar a esta clase desde nuestras ViewModel. Otro punto de la navegación que cambia con respecto a Windows Phone es la cache de las páginas visitadas. En Windows Phone si llamábamos al método GoBack del NavigationService, automáticamente volvíamos a la página anterior, que se conservaba en el estado en el que la habíamos dejado.

En Windows 8 esto cambia, por defecto las instancias de las páginas no se conservan, la pila de navegación solo conoce el tipo y cuando hacemos un GoBack (o un GoForward, que sí está soportado en Windows 8 y nos ahorrará problemas de navegación circular) simplemente se crea una nueva instancia de la página anterior, perdiendo el estado que tenía. Este comportamiento puede ser modificado mediante la propiedad NavigationCacheMode presente en la clase Page:

Cabecera de una página Xaml
  1. <Page
  2.     x:Class=»Geeks.ms.BlankPage»
  3.     xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
  4.     xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
  5.     xmlns:local=»using:Geeks.ms»
  6.     xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″
  7.     xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″
  8.     mc:Ignorable=»d»
  9.     NavigationCacheMode=»Enabled»
  10.     DataContext=»{Binding Path=StartPage, Source={StaticResource VmLocator}}«>

La propiedad NavigationCacheMode puede tener tres valores:

  1. Enabled: La instancia se conserva en memoria, siempre y cuando no superemos el número de páginas máximo que hayamos establecido en nuestro Frame principal.
  2. Required: La instancia de esta página no cuenta en el total de páginas indicado en el Frame principal, simplemente debe ser conservada y no será destruida aunque se supere el máximo.
  3. Disabled: Este es el valor por defecto, se crea una nueva instancia por cada visita.

Por defecto, el objeto Frame establece la propiedad CacheSize con un tamaño de 10 páginas, aunque podemos modificarlo simplemente estableciendo la propiedad CacheSize de nuestro RootFrame:

CacheSize
  1. RootFrame.CacheSize = 12;

Algo que debemos tener en cuenta es que, si marcamos la propiedad NavigationCacheMode como Enabled o Required, si al navegar a una página se encuentra su instancia en memoria, se usará esta instancia. Si tenemos una página cuyo contenido cambiará cada vez que accedamos a ella, lo mejor es no habilitar el cache, pues no lo necesitamos.

Algo sobre lo que todavía estoy investigando y realizando pruebas es todo lo relacionado al IoC, en cuanto haya revisado todas las opciones que hay, os contaré mis ideas finales!.

Conclusión

Esto ha sido una breve introducción a las aplicaciones Metro en C#, desde el punto de vista de un desarrollador Windows Phone. En el próximo artículo veremos más detalles sobre Expression Blend 5, un poco de Async, el emulador de Windows 8 y un ejemplo de aplicación metro, así que empezad a descargar Windows 8 y Visual Studio 11 si no lo tenéis ya, es realmente divertido y vale la pena ponerle las manos encima cuanto antes.

Un saludo y Happy Coding!