Share via


Exercise 2: Load and Store Pictures

In this exercise you will:

  • Save and load captured pictures to and from local isolated storage
  • Save captured pictures to the phone’s pictures hub

Task 1 – Saving and Loading Pictures to and from Isolated Storage

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

Before you begin, please open the Source\Ex2 – LoadAndStorePictures\Begin.sln solution file, and review the code. The project is comprised of Models, Pages, Resources, the Application class, and the assets library.

In this task you will learn how to use isolated storage to save and load captured pictures content and relevant details.

  1. 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.
  2. 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.

    C#

    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", () => { }); } }

  3. Implement the NotificationBoxCommand by adding the captured picture instance to the PictureRepository singleton pictures list located in the Models folder.

    C#

    private NotificationBoxCommand SaveToLocalStorage { get { return new NotificationBoxCommand("local store", () => { PictureRepository.Instance.Pictures.Add(Model); }); } }
    Note:
    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.

  4. 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.

    C#

    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); }

  5. In the Deserialize method, read the data in the same order you’ve written it.

    C#

    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(); }

  6. Open the CapturedPicture.cs file and override both Serialize and Deserialize methods.

    C#

    public override void Serialize(BinaryWriter writer) { } public override void Deserialize(BinaryReader reader) { }

  7. 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.

    C#

    public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(ImageBytes.Length); writer.Write(ImageBytes); writer.WriteString(FileName); }

  8. In the Deserialize method, first call the base class Deserialize, and then read the data in the same order you’ve written it.

    C#

    public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); int bytesCount = reader.ReadInt32(); ImageBytes = reader.ReadBytes(bytesCount); FileName = reader.ReadString(); }

  9. 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.

    C#

    public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { }

  10. Open the CapturedPicturePage.xaml.cs file and call the SaveToLocalStorage method from the NotificationBoxCommand and navigate back to the previous page.

    C#

    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(); }); } }

  11. Open the file named PictureRepository.cs under Models folder. In the SaveToLocalStorage method call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file.

    C#

    public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }

  12. Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.

    C#

    public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(directory); }

  13. 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.

    C#

    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)) { } }

  14. 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.

    C#

    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); } } }

  15. 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.

    C#

    public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { }

  16. To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication in the LoadFromLocalStorage empty method.

    C#

    public CapturedPicture LoadFromLocalStorage(string fileName, string directory) { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }

  17. 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.

    C#

    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)) { } }

  18. 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.

    C#

    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; } } }

  19. To load all the pictures at start time, add another method called LoadAllPicturesFromIsolatedStorage to the PictureRepository class.

    C#

    private void LoadAllPicturesFromIsolatedStorage() { }

  20. To the LoadAllPicturesFromIsolatedStorage empty method, add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file.

    C#

    private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); }

  21. Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.

    C#

    private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); }

  22. Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures.

    C#

    private void LoadAllPicturesFromIsolatedStorage() { var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); isoFile.EnsureDirectory(IsolatedStoragePath); var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg")); }

  23. Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier.

    C#

    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); } }

  24. Add each captured picture instance to the pictures collection.

    C#

    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); } }

  25. Call the LoadAllPicturesFromIsolatedStorage method from the PictureRepository constructor.

    C#

    private PictureRepository() { LoadSampleImages(); LoadAllPicturesFromIsolatedStorage(); }

  26. 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

Task 2 – Saving Pictures to the Pictures Hub

In this task you will learn how to use the XNA library to save the captured pictures content to the phone’s pictures hub.

Note:
The pictures hub doesn’t exist on the WP7 emulator. To test the result of this task you must deploy and run it on a real WP7 device.

  1. To save the captured picture to the pictures hub, open the PictureRepository singleton class and add a new method named SaveToPicturesHub that has one parameter of the type CapturedPicture.

    C#

    public void SaveToPicturesHub(CapturedPicture picture) { }

  2. Add a reference to the Microsoft.Xna.Framework .
  3. In the SaveToPicturesHub empty method, create a new instance of type Microsoft.Xna.Framework.Media.MediaLibrary and call the MediaLibrary.SavePicture method with the captured picture file name and image bytes.

    C#

    public void SaveToPicturesHub(CapturedPicture picture) { var mediaLibrary = new MediaLibrary(); mediaLibrary.SavePicture(picture.FileName, picture.ImageBytes); }

  4. To invoke this method from the notification box added in previous task, open the CapturedPicturePage.xaml.cs file and locate the ApplicationBarSavePicture_Click event handler.
  5. Add additional NotificationBoxCommand to the notification box which invokes the SaveToPicturesHub method you’ve just added and navigates back afterward.

    C#

    private void ApplicationBarSavePicture_Click(object sender, EventArgs e) { NotificationBox.Show( "Save picture", "Where would you like to save the picture?", SaveToPicturesHub, SaveToLocalStorage); } private NotificationBoxCommand SaveToPicturesHub { get { return new NotificationBoxCommand("pictures hub", () => { PictureRepository.Instance.SaveToPicturesHub(Model); NavigationService.GoBack(); }); } }

  6. To test the results on a real device, make sure that the WP7 device is connected and Zune software is running. In Visual Studio, select ‘Windows Phone 7 Device’ for the debug/deploy target, build and deploy the application, disconnect the device and run the application . Take a picture, click the save app bar button, and choose pictures hub. Exit the phone application, navigate to the pictures hub and you should find your new picture there.

    Note:
    If you’ve installed the Windows Phone Developer Tools October 2010 Update, there is a tool called WPConnect.exe located in %ProgramFiles%\Microsoft SDKs\Windows Phone\v7.0\Tools\WPConnect. The Windows Phone Connect Tool allows you to establish serial or connectivity to the device without running the Zune software. This topic will provide guidance for installing the tool and using it to debug your Windows Phone applications. More information about this tool can be foundhttps://msdn.microsoft.com/en-us/library/gg180729(v=vs.92).aspxhere.

    This concludes the exercise.

    Note:
    You can find the complete solution for this exercise at Source\Ex2 - LoadAndStorePictures\End.