Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

PinCodeKeeper WP7 app – Using Isolated Storage to save, load and delete Pin Codes

DZone's Guide to

PinCodeKeeper WP7 app – Using Isolated Storage to save, load and delete Pin Codes

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

The add new pin code functionality (completed in previous article) was the last main functionality for the PinCodeKeeper and the time has come to start using real data instead of mock up data. I will now implement Isolated Storage so that I can save/store new pin codes, retrieve all saved pin codes and delete pin codes from the storage.

The first thing I do is to add a new class that I call IsolatedStorageUtil.cs, this class will contain all functionality I need for saving, retrieving, deleting and some other utility methods. To use the DataContractSerializer you must add a reference to System.Runtime.Serialization.

You can see my IsolatedStorageUtil.cs class below.

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;

<span id="more-2325"></span>

namespace PinCodeKeeper
{
public class IsolatedStorageUtil<TDataType>
{
private readonly DataContractSerializer _serializer;
private IsolatedStorageFile _isolatedStorageFile;

public IsolatedStorageUtil()
{
_serializer = new DataContractSerializer(typeof(TDataType));
}

private IsolatedStorageFile IsolatedStorageFile
{
get { return _isolatedStorageFile ?? (_isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()); }
}

//Check if file exists
public bool FileExists(string fileName, string directoryName)
{
string targetFileName = directoryName == null ? fileName : String.Format("{0}/{1}", directoryName, fileName);
return IsolatedStorageFile.FileExists(targetFileName);
}

//Check if directory exists
public bool DirectoryExists(string directoryName)
{
return IsolatedStorageFile.DirectoryExists(directoryName);
}

//Get all filenames in a given directory
public string[] GetFileNames(string directoryName, string fileType)
{
string[] fileNames = new string[0];
if (DirectoryExists(directoryName))
{
fileNames = IsolatedStorageFile.GetFileNames(directoryName + "/*." +fileType);
}
return fileNames;
}

//Save data to the isolated storage, the data must be serializable
public void SaveData(TDataType sourceData, String fileName, string directoryName)
{
string targetFileName = directoryName == null ? fileName : String.Format("{0}/{1}", directoryName, fileName);

if (directoryName != null && !IsolatedStorageFile.DirectoryExists(directoryName))
//Create directory if needed
IsolatedStorageFile.CreateDirectory(directoryName);
try
{
using (IsolatedStorageFileStream targetFile = IsolatedStorageFile.CreateFile(targetFileName))
{
//Serialize file data
_serializer.WriteObject(targetFile, sourceData);
}
}
catch (Exception e)
{
//If exception just delete file
IsolatedStorageFile.DeleteFile(targetFileName);
}
}

//Load data from storage, retrieved the deserialized object
public TDataType LoadData(string fileName, string directoryName)
{
TDataType retVal = default(TDataType);
string targetFileName = directoryName == null ? fileName : String.Format("{0}/{1}", directoryName, fileName);

if (IsolatedStorageFile.FileExists(targetFileName))
using (IsolatedStorageFileStream sourceStream = IsolatedStorageFile.OpenFile(targetFileName, FileMode.Open))
{
//Deserialize file data
retVal = (TDataType)_serializer.ReadObject(sourceStream);
}
return retVal;
}

//Delete a given file
public void DeleteFile(string fileName, string directoryName)
{
string targetFileName = directoryName == null ? fileName : String.Format("{0}/{1}", directoryName, fileName);
if (IsolatedStorageFile.FileExists(targetFileName))
{
IsolatedStorageFile.DeleteFile(targetFileName);
}
}
}
}

 

Next I need to ensure that the PinCode object that I will be storing is serializable. The first problem I encountered in my PinCode.cs was that I was using a multi-dimensional array ([,]) this is not supported by System.Runtime.Serialization so I changed it to be an array-of-arrays, also called jagged arrays ([][]). Then I added DataContract attribute to the the PinCode.cs class and DataMember attributes to the class members, this way the PinCode.cs class can be serialized.

You can see my PinCode.cs class below.

using System.Runtime.Serialization;

namespace PinCodeKeeper.Model
{
[DataContract]
public class PinCode
{

[DataMember]
public string Name { get; set; }
[DataMember]
public string[][] PinCodeMatrix { get; set; }
[DataMember]
public string FileName { get; set; }
}
}

Listing all saved pin codes

In the PinCodeListPresenter.cs I have been using a method called MockUpPinCodes to create some fake pin codes and have them displayed. Now I will replace this method by a method called GetPinCodesFromIsolatedStorage. So now when the PinCodeListView is initialized it will display pin codes that are retrieved from the Isolated Storage.

You can see the InitializeView and GetPinCodesFromIsolatedStorage methods I have in PinCodeListPresenter.cs below.

// Initialize view with PinCodeList.
public void InitializeView()
{
_viewData = new PinCodeList();
_viewData.PinCodes = new ObservableCollection<PinCode>();

GetPinCodesFromIsolatedStorage();
//MockUpPinCodes();

_view.InitializeView(_viewData);
}

// Read pin codes from isolated storage and
// add them to viewData.
private void GetPinCodesFromIsolatedStorage()
{
var isolatedStorage = new IsolatedStorageUtil<PinCode>();
if (isolatedStorage.DirectoryExists("pincodes"))
{
//Get all file names for xml files in the pincodes directory
var fileNames = isolatedStorage.GetFileNames("pincodes", "xml");
foreach (string filename in fileNames)
{
//Retrieve, deserialize and add to view data
_viewData.PinCodes.Add(isolatedStorage.LoadData(filename, "pincodes"));
}
}
}

Saving a pin code

When saving a pin code I simply have the PinCode object serialized and saved as a xml file in the Isolated Storage.

You can see the SavePinCode method in NewPinCodePresenter.cs below

public void SavePinCode(string[][] pinCodeMatrix, string pinCodeName)
{
//Use timestamp as filename
string fileName = DateTime.Now.Ticks + ".xml";
PinCode pinCode = new PinCode { PinCodeMatrix = pinCodeMatrix, Name = pinCodeName, FileName = fileName};
//Save to isolated storage
var isolatedStorage = new IsolatedStorageUtil<PinCode>();
isolatedStorage.SaveData(pinCode, fileName, "pincodes");
//Add as selected pin code so it will be shown directly
MainModel.Instance.SelectedPinCode = pinCode;
}

Deleting a pin code

Deleting a stored pin code is done in the PinCodePresenter.cs and below you can see the DeletePinCode method I use for this.

// Delete pin code
public void DeletePinCode()
{
//Delete from isolated storage
var isolatedStorage = new IsolatedStorageUtil<PinCode>();
isolatedStorage.DeleteFile(_viewData.FileName, "pincodes");
//Remove from main model
MainModel.Instance.SelectedPinCode = null;
}

That’s all there is to it, pin codes are now stored in the Isolated Storage and we can retrieve and delete stored pin codes.

The next step for the PinCodeKeeper app will be to add internationalization support.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Published at DZone with permission of Per Ola Sæther, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}