Inside the Implementation

0
118

Now is a good time to walk through the code that implements isolated storage in the Tailspin mobile application in more detail. As you go through this section, you may want to download the Microsoft Visual Studio® development system solution for the Tailspin Surveys application from CodePlex (http://go.microsoft.com/fwlink/?LinkId=205602).

You can find the code that implements isolated storage access in the Tailspin mobile client application in the Services/Stores folder in the TailSpin.PhoneClient.

Application Settings

The user enters application settings data on the AppSettingsView and FilterSettingsView pages in the Surveys application. The interface ISettingsStore defines the data items that the application saves as settings. The following code example shows this interface.

C#
public interface ISettingsStore
{
string Password { get; set; }
string UserName { get; set; }
bool SubscribeToPushNotifications { get; set; }
bool LocationServiceAllowed { get; set; }
}

The following code example shows how the application implements this interface to save the value of the Password property in the ApplicationSettings dictionary in the application’s isolated storage.

C#
public class SettingsStore : ISettingsStore
{
private const string PasswordSettingDefault = “”;
private const string PasswordSettingKeyName =
“PasswordSetting”;

private readonly IsolatedStorageSettings isolatedStore;
public SettingsStore()
{
this.isolatedStore =
IsolatedStorageSettings.ApplicationSettings;
}
public string Password
{
get { return this.GetValueOrDefault(PasswordSettingKeyName,
PasswordSettingDefault); }
set { this.AddOrUpdateValue(PasswordSettingKeyName, value); }
}

private void AddOrUpdateValue(string key, object value)

{
bool valueChanged = false;
try
{
// If the new value is different, set the new value.
if (this.isolatedStore[key] != value)
{
this.isolatedStore[key] = value;
valueChanged = true;
}
}
catch (KeyNotFoundException)
{
this.isolatedStore.Add(key, value);
valueChanged = true;
}
catch (ArgumentException)
{
this.isolatedStore.Add(key, value);
valueChanged = true;
}
if (valueChanged)
{
this.Save();
}
}

private T GetValueOrDefault<T>(string key, T defaultValue)
{
T value;
try
{
value = (T)this.isolatedStore[key];
}
catch (KeyNotFoundException)
{
value = defaultValue;
}
catch (ArgumentException)
{
value = defaultValue;
}

return value;
}
private void Save()
{
this.isolatedStore.Save();
}
}

Survey Data

The application saves the local survey data in isolated storage as a serialized SurveysList object. The following code example shows the definition of the SurveysList object that uses the model classes SurveyTemplate and SurveyAnswer. The SurveyTemplate class is a model class that defines a survey and includes the question types, question text, and survey metadata. The SurveyAnswer class is a model class that defines the responses collected by the surveyor

C#
public class SurveysList
{
public SurveysList()
{
this.LastSyncDate = string.Empty;
}
public List<SurveyTemplate> Templates { get; set; }
public List<SurveyAnswer> Answers { get; set; }
public string LastSyncDate { get; set; }
}

The following code example shows how the SurveyStore class (that implements the ISurveyStore interface) performs the serialization and deserialization of the SurveyList instance to and from isolated storage.

C#
private readonly string storeName;
public SurveyStore(string storeName)
{

this.storeName = storeName;
this.Initialize();
}
public SurveysList AllSurveys { get; set; }

public void SaveStore()
{
lock (this)
{
using (var filesystem =
IsolatedStorageFile.GetUserStoreForApplication())
{
using (var fs = new IsolatedStorageFileStream(
this.storeName, FileMode.Create, filesystem))
{
var serializer = new System.Runtime.Serialization
.Json.DataContractJsonSerializer(typeof(SurveysList));
serializer.WriteObject(fs, this.AllSurveys);
}
}
}
}

private void Initialize()
{
lock (this)
{
using (var filesystem =
IsolatedStorageFile.GetUserStoreForApplication())
{
if (!filesystem.FileExists(this.storeName))
{
this.AllSurveys = new SurveysList
{
Templates = new List<SurveyTemplate>(),
Answers = new List<SurveyAnswer>()
};
}
else
{

using (var fs = new IsolatedStorageFileStream(
this.storeName, FileMode.Open, filesystem))
{
var serializer = new System.Runtime.Serialization
.Json.DataContractJsonSerializer(typeof(SurveysList));
this.AllSurveys =
serializer.ReadObject(fs) as SurveysList;
}
}
}
}
}

The following code example shows the interface in the TailSpin. PhoneClient project that defines the operations that the application can perform on the survey store. The SurveyStore class implements this interface.

C#
using System.Collections.Generic;
using Models;
public interface ISurveyStore
{
string LastSyncDate { get; set; }
IEnumerable<SurveyTemplate> GetSurveyTemplates();
IEnumerable<SurveyAnswer> GetCompleteSurveyAnswers();
void SaveSurveyTemplates(IEnumerable<SurveyTemplate> surveys);
void SaveSurveyAnswer(SurveyAnswer answer);
SurveyAnswer GetCurrentAnswerForTemplate(
SurveyTemplate template);
void DeleteSurveyAnswers(
IEnumerable<SurveyAnswer> surveyAnswers);
void SaveStore();
}

The SurveyListViewModel class calls the GetSurveyTemplates method to retrieve a list of surveys to display to the user. The Survey ListViewModel class creates filtered lists of surveys (new surveys, favorite surveys, and so on) after it has added the surveys to CollectionViewSource objects.

The SurveysSynchronisationService class uses the GetComplete SurveyAnswers, SaveSurveyTemplates, GetCurrentAnswerFor Template, and DeleteSurveyAnswers methods to manage the survey data stored on the device.

The TakeSurveyViewModel class uses the GetCurrentAnswer ForTemplate and SaveSurveyAnswer methods to retrieve and save survey responses on the device.