Windows Phone –Tutorial X IsolatedStorage

IsolatedStorage en Windows Phone es el mismo concepto que apareció en la versión 2 de Silverlight, nos va a permitir almacenar datos en el dispositivo para ser utilizados por la aplicación. Únicamente nuestra aplicación podrá utilizarlos, estos datos no pueden ser compartidos entre aplicaciones, si quieres compartir datos entre dos aplicaciones deberás utilizar la nube para ello.

En Windows Phone IsolatedStorage tiene dos modalidades:

  • Local Settings: La utilizaremos para guardar settings de la aplicación solo vamos a poder almacenar pares de clave/valor como si fuese un diccionario
  • Files & Folders: Nos permite crear carpetas y ficheros que almacenen cualquier tipo de información.

En la imagen de abajo extraída de la MSDN vemos de modo gráfico las dos posibilidades.

isolatedstorage

Para utilizar IsolatedStorage deberemos de utilizar las clases del assembly System.IO.IsolatedStorage, dentro de este assembly tenemos las clases IsolatedStorageFile y IsolatedStorageSettings para realizar los dos tipos antes mencionados.

IsolatedStorageSettings 

Permite almacenar pares clave/valor como si fuese un diccionario para poder cargarlos la siguiente vez que realicemos la carga de la aplicación. Vamos a verlo con una aplicación donde almacenaremos las settings de la aplicación.

image

El Xaml seria muy sencillo y no tendría problemas

1 x:Name="ContentGrid" 2 Grid.Row="1"> 3 <Grid.RowDefinitions> 4 <RowDefinition /> 5 <RowDefinition /> 6 <RowDefinition /> 7 <RowDefinition /> 8 <RowDefinition /> 9 <RowDefinition /> 10 <RowDefinition /> 11 </Grid.RowDefinitions> 12 <Grid.ColumnDefinitions> 13 <ColumnDefinition Width="189*" /> 14 <ColumnDefinition Width="291*" /> 15 </Grid.ColumnDefinitions> 16 <TextBlock Grid.Row="1" Height="36" HorizontalAlignment="Right" Name="textBlock1" Text="Usuario:" VerticalAlignment="Center" TextAlignment="Right" Grid.ColumnSpan="1" /> 17 <TextBox Grid.Column="1" Text="{Binding SettingsUser.UserName, Mode=TwoWay}" Grid.Row="1" HorizontalAlignment="Left" Name="txtUser" VerticalAlignment="Center" Height="77" Width="295" /> 18 <TextBlock Height="36" HorizontalAlignment="Right" Name="textBlock2" Text="Password:" TextAlignment="Right" VerticalAlignment="Center" Grid.Row="2" Grid.ColumnSpan="1" /> 19 <PasswordBox Password="{Binding SettingsUser.Password, Mode=TwoWay}" Grid.Column="1" Grid.Row="2" Height="77" HorizontalAlignment="Left" Name="txtPassword" VerticalAlignment="Top" Width="295" /> 20 <TextBlock Height="36" HorizontalAlignment="Right" Name="textBlock3" Text="Correo Electronico:" TextAlignment="Right" VerticalAlignment="Center" Grid.Row="3" Grid.ColumnSpan="1" /> 21 <TextBox Text="{Binding SettingsUser.Email, Mode=TwoWay}" Height="77" HorizontalAlignment="Left" Name="txtEmail" VerticalAlignment="Center" Width="295" Grid.Row="3" Grid.Column="1"> 22 <TextBox.InputScope> 23 <InputScope> 24 <InputScopeName NameValue="EmailNameOrAddress" /> 25 </InputScope> 26 </TextBox.InputScope> 27 </TextBox> 28 </Grid> 29 </Grid> 30 31 <phone:PhoneApplicationPage.ApplicationBar> 32 <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False"> 33 <shell:ApplicationBarIconButton x:Name="appbar_btnSave" Click="appbar_btnSave_Click" IconUri="/Images/appbar.save.rest.png" Text="Siguiente"> 34 </shell:ApplicationBarIconButton> 35 </shell:ApplicationBar> 36 </phone:PhoneApplicationPage.ApplicationBar> 37

He creado un modelo con las settings del usuario que queremos guardar

1 public class Settings 2 { 3 public string UserName { get; set; } 4 public string Password { get; set; } 5 public bool RememberPassword { get; set; } 6 public string Email { get; set; } 7 }

 

En la ViewModel he creado un comando para que cuando pulse en el botón de salvar se guarden las settings del usuario.

1 ............... 2 private Settings _settingsUser = null; 3 public Settings SettingsUser 4 { 5 get 6 { 7 return _settingsUser; 8 } 9 set 10 { 11 _settingsUser = value; 12 RaisePropertyChanged("SettingsUser"); 13 } 14 } 15 public RelayCommand SaveCommand { get; private set; } 16 /// <summary> 17 /// Initializes a new instance of the MainViewModel class. 18 /// </summary> 19 public MainViewModel() 20 { 21 if (IsInDesignMode) 22 { 23 // Code runs in Blend --> create design time data. 24 } 25 else 26 { 27 _settingsUser = new Settings(); 28 IsolatedStorageHelper ish = new IsolatedStorageHelper(); 29 ish.RestoreEntity(_settingsUser); 30 SaveCommand = new RelayCommand(Save); 31 } 32 } 33 34 private void Save() 35 { 36 if (SettingsUser != null) 37 { 38 IsolatedStorageHelper ish = new IsolatedStorageHelper(); 39 ish.SaveEntity(SettingsUser); 40 } 41 42 } 43

Ahora al grano si os fijáis en el método Save he creado una nueva clase IsolatedStorageHelper  en la que he hecho un pequeño wrapping de IsolatedStorageSettings esta clase permite salvar un par clave valor o toda una entidad, es decir, se recorre las propiedades y va salvando cada una de las propiedades.

La clase IsolatedStorageSettings funciona como un diccionario, tiene un método Contains(string key) que comprueba si esta la clave ya almacenada, si no esta almacenada la añade con el método Add(strinh key, object value) y si ya esta almacenada la asigna. Como veis es muy fácil de utilizar.

A la hora de recuperar las Settings utilizo el metodo RestoreEntity que recupera toda la entidad, esta baso en el metodo Restore que recupera un valor a partir de su clave como en un diccionario.

Aquí tenéis el código de IsolatedStorageHelper 

1 public class IsolatedStorageHelper 2 { 3 4 /// <summary> 5 /// Salva una entidad en IsolatedStorageSettings 6 /// </summary> 7 /// <param name="entity"></param> 8 public void SaveEntity(Object entity) 9 { 10 var propInfo = entity.GetType().GetProperties(); 11 if (null != propInfo) 12 { 13 for (int i = 0; i < propInfo.Length; i++) 14 { 15 Backup(propInfo[i].Name, propInfo[i].GetValue(entity, null)); 16 17 } 18 } 19 } 20 21 /// <summary> 22 /// Restaura una entidad completa 23 /// </summary> 24 /// <param name="entity"></param> 25 public void RestoreEntity(Object entity) 26 { 27 var propInfo = entity.GetType().GetProperties(); 28 if (null != propInfo) 29 { 30 for (int i = 0; i < propInfo.Length; i++) 31 { 32 propInfo[i].SetValue(entity,Restore(propInfo[i].Name), null); 33 } 34 } 35 } 36 37 /// <summary> 38 /// Salva una par clave/valor en IsolatedStorageSettings 39 /// </summary> 40 /// <param name="token"></param> 41 /// <param name="value"></param> 42 /// <returns></returns> 43 public bool Backup(string token, object value) 44 { 45 if (null == value) 46 return false; 47 48 var store = IsolatedStorageSettings.ApplicationSettings; 49 if (store.Contains(token)) 50 store[token] = value; 51 else 52 store.Add(token, value); 53 54 store.Save(); 55 return true; 56 } 57 58 /// <summary> 59 /// Devuelve un valor almacendao a partir de su clave 60 /// </summary> 61 /// <param name="token"></param> 62 /// <returns></returns> 63 public object Restore(string token) 64 { 65 var store = IsolatedStorageSettings.ApplicationSettings; 66 if (!store.Contains(token)) 67 return null; 68 69 return store[token]; 70 } 71 } 72

Es importante saber que a la hora de debugear las settings estas se quedan almacenadas mientras esta el emulador levando, si lo cerráis y volvéis a ejecutar la aplicación habéis perdido todo lo grabado. Una vez que deis al botón de guardar cerrar la aplicación desde el botón Stop de Visual Studio cierra la aplicación pero mantiene el emulador levantado.

Aquí tenéis el código para descargarlo

 

IsolatedStorageSettings 

Vamos a utilizar la aplicación anterior para guardar las settings de usuario esta vez en un fichero, en vez de el diccionario IsolatedStorageSettings. Vamos a grabar la instancia se Settings en un solo archivo, el formato de grabación puede ser cualquiera un fichero txt, un xml… En mi caso voy a grabar en un fichero con la extensión que quiera pero con el objeto serializado para que ocupe lo mínimo posible.

Para ello a nuestra clase Settings (Model) la vamos a decorar con el atributo DataContract y a cada propiedad con el atributo DataMember porque vamos a utilizar DataContractSerializer para la serialización del objeto.

Para salvar nuestro objeto hemos extendido la clase IsolatedStorageHelper  con nuevos métodos para Salvar y Recuperar un objeto.

1 public void SaveEntity<T>(string name, T objectToSave) 2 { 3 using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication()) 4 using (IsolatedStorageFileStream storageFileStream = new IsolatedStorageFileStream(name, System.IO.FileMode.Create, storageFile)) 5 { 6 DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 7 serializer.WriteObject(storageFileStream, objectToSave); 8 } 9 } 10 11 public T RestoreEntity<T>(string name) where T : class, new() 12 { 13 T loadedObject = null; 14 using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication()) 15 using (IsolatedStorageFileStream storageFileStream = new IsolatedStorageFileStream(name, System.IO.FileMode.OpenOrCreate, storageFile)) 16 { 17 if (storageFileStream.Length > 0) 18 { 19 DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 20 loadedObject = serializer.ReadObject(storageFileStream) as T; 21 } 22 if (loadedObject == null) 23 { 24 loadedObject = new T(); 25 } 26 } 27 28 return loadedObject; 29 }

Como podéis ver en el código de arriba el manejo es igual que en Silverlight se genera un archivo y se escribe o lee sobre el, no hay mucho misterio.

 

Os dejo el código

 

4 comentarios en “Windows Phone –Tutorial X IsolatedStorage”

  1. Hola David por ahora no lo soporta, no sabremos en la nueva actualización de febrero si vendra o no, a mi me da en la nariz que no. Te dejo abajo un extracto de un artidulo de silverlighthack en el que yo estoy totalmente de acuerdo
    Because of the list of limitations above, the Windows Phone 7 only supports Silverlight mobile applications. If you have a Silverlight 2, 3 or 4 application on the web and browse it with a Windows 7 Phone, it will not work. That is a ridiculous limitation. The Windows Phone 6.5 includes a browser called Skyfire (http://www.skyfire.com) that can already surface Silverlight content on a mobile device. I don’t know if this is a technical reason or a way for Microsoft to lock down what “apps” are surfaced on Windows Phone 7 (like Apple does with the iPhone).

    What is even more insulting about this is that the Silverlight beta for Symbian Nokia S60 phones supports out of the browser Silverlight: http://mobile.engadget.com/2010/03/20/silverlight-beta-comes-to-s60-5th-edition/ . Doesn’t that seem backwards?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *