Isolated storage enables managed applications to create and maintain local storage. The mobile architecture is similar to Silverlight-based applications on Windows. All I/O operations are restricted to isolated storage and do not have direct access to the underlying operating system file system. Ultimately, this helps to provide security and prevents unauthorized access and data corruption.
Application developers have the ability to store data locally on the phone, again leveraging all the benefits of isolated storage, including protecting data from other applications
In this task you will learn how to use isolated storage to save and load captured pictures content and relevant details.
- To save a captured picture in isolated storage, open the CapturedPicturePage.xaml.cs file and locate the ApplicationBarSavePicture_Click event handler, which handles the save app bar button click event.
Use the NotificationBox class located in the assets project to display a custom message to the user to ask where to save the captured picture. To display a message, call the NotificationBox.Show static method with Title, Message, and one MessageBoxCommand for handling the isolated storage.
private void ApplicationBarSavePicture_Click(object sender, EventArgs e) { NotificationBox.Show( "Save picture", "Where would you like to save the picture?", SaveToLocalStorage); } private NotificationBoxCommand SaveToLocalStorage { get { return new NotificationBoxCommand("local store", () => { }); } }
Implement the NotificationBoxCommand by adding the captured picture instance to the PictureRepository singleton pictures list located in the Models folder.
private NotificationBoxCommand SaveToLocalStorage { get { return new NotificationBoxCommand("local store", () => { PictureRepository.Instance.Pictures.Add(Model); }); } }
You’re going to use serialization to store and load an object from Isolated Storage. There are several options for serializing an object in WP7: XML, Json and Binary. In our case we’ll use Binary serialization as it yields the best performance when using a real device.
To support binary serialization, open the Picture.cs file and implement the ISerializable interface located in the assets project, as virtual methods. In the Serialize method, store the Position, Address, Note, and DateTaken properties. Use the BinaryWriterExtensions located in the assets project for saving strings.
public virtual void Serialize(BinaryWriter writer) { var position = Position ?? GeoCoordinate.Unknown; writer.Write(position.Latitude); writer.Write(position.Longitude); writer.WriteString(Address); writer.WriteString(Note); writer.WriteString(DateTaken); }
In the Deserialize method, read the data in the same order you’ve written it.
public virtual void Deserialize(BinaryReader reader) { double latitude = reader.ReadDouble(); double longitude = reader.ReadDouble(); Position = new GeoCoordinate(latitude, longitude); Address = reader.ReadString(); Note = reader.ReadString(); DateTaken = reader.ReadString(); }
Open the CapturedPicture.cs file and override both Serialize and Deserialize methods.
public override void Serialize(BinaryWriter writer) { } public override void Deserialize(BinaryReader reader) { }
In the Serialize method, first call the base class Serialize, and then write the ImageBytes.Length, ImageBytes, and FileName properties. Use the BinaryWriterExtensions located in the assets project for saving strings.
public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(ImageBytes.Length); writer.Write(ImageBytes); writer.WriteString(FileName); }
In the Deserialize method, first call the base class Deserialize, and then read the data in the same order you’ve written it.
public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); int bytesCount = reader.ReadInt32(); ImageBytes = reader.ReadBytes(bytesCount); FileName = reader.ReadString(); }
Add a new empty method called SaveToLocalStorage to the PictureRepository that handles the save operation. This method gets two parameters: the captured picture instance and the name of the pictures folder in the isolated storage.
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { }
Open the CapturedPicturePage.xaml.cs file and call the SaveToLocalStorage method from the NotificationBoxCommand and navigate back to the previous page.
private NotificationBoxCommand SaveToLocalStorage { get { return new NotificationBoxCommand("local store", () => { // Cache image in repository. PictureRepository.Instance.Pictures.Add(Model); PictureRepository.Instance.SaveToLocalStorage(Model, PictureRepository.IsolatedStoragePath); NavigationService.GoBack(); }); } }
Open the file named PictureRepository.cs under Models folder. In the SaveToLocalStorage method call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file.
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }
Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(directory); }
Combine the pictures folder and captured picture file name and use this path to create a new file in the isolated storage by calling IsolatedStorageFile.CreateFile inside a using clause.
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(directory); string filePath = Path.Combine(directory, capturedPicture.FileName); using (var fileStream = isoFile.CreateFile(filePath)) { } }
Inside the using clause, create a BinaryWriter instance for serializing the CapturedPicture instance and then call the CapturedPicture.Serialize method to serialize the captured picture.
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(directory); string filePath = Path.Combine(directory, capturedPicture.FileName); using (var fileStream = isoFile.CreateFile(filePath)) { using (var writer = new BinaryWriter(fileStream)) { capturedPicture.Serialize(writer); } } }
To load all saved pictures and add them to the pictures list page, add a new empty method called LoadFromLocalStorage to the PictureRepository class. This method gets two parameters: the picture file name and the pictures directory, and one return value: the captured picture.
public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { }
To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication in the LoadFromLocalStorage empty method.
public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }
Combine the directory and file name, and use the path to open the picture file from the isolated storage by using the IsolatedStorageFile.OpenFile method inside a using clause.
public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); string filePath = Path.Combine(directory, fileName); using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read)) { } }
Inside the using clause, create a BinaryReader instance for deserializing the CapturedPicture instance. In the using clause, create a new instance of the type CapturedPicture called CapturedPicture.Deserialize to deserialize the captured picture and return it.
public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); string filePath = Path.Combine(directory, fileName); using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read)) { using (var reader = new BinaryReader(fileStream)) { var capturedPicture = new CapturedPicture(); capturedPicture.Deserialize(reader); return capturedPicture; } } }
To load all the pictures at start time, add another method called LoadAllPicturesFromIsolatedStorage to the PictureRepository class.
private void LoadAllPicturesFromIsolatedStorage() { }
To the LoadAllPicturesFromIsolatedStorage empty method, add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file.
private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }
Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); }
Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures.
private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg")); }
Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier.
private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg")); foreach (var pictureFile in pictureFiles) { var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath); } }
Add each captured picture instance to the pictures collection.
private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg")); foreach (var pictureFile in pictureFiles) { var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath); _pictures.Add(picture); } }
Call the LoadAllPicturesFromIsolatedStorage method from the PictureRepository constructor.
private PictureRepository() { LoadSampleImages(); LoadAllPicturesFromIsolatedStorage(); }
To test the result, build and run the application. Then capture an image, write a note, click the save app button, and then click the ‘local store’ message button. This should save the image and navigate back to the picture list. You should see the picture at the bottom of the list. Click Back to close the application, and then run it again. The picture you’ve just saved should appear at the bottom of the list.
Figure 3
Save and Load from Isolated Storage
In this task you will learn how to use the XNA library to save the captured pictures content to the phone’s pictures hub.