Writing Settings to Isolated Storage

OK, todays post will be about using isolated storage to save application settings. In some of my applications, I find that sometimes it is useful to store settings relating to custom views and UI settings. For instance, when a user goes into a control which has a datagridview on it, wouldn’t it be nice if we could remember the column positions, ordering, filtering etc. which was applied last time the user accessed that control?

You could do this in a variety of ways, but I find the easiest is to use isolated storage. Isolated storage can be thought of as a small portion of the hard disk which you can almost guarantee your application has access to and can be used to write pretty much anything that you could write to a regular folder on your hard disk.

So, what I thought was to create a ApplicationSettingsManager class which would act as a gateway to the settings. Each method in ApplicationSettingsManager is a static method so that it can be called without instantiating an object. The class looks a little like this :-

public class ApplicationSettingsManager

{

public static void SaveSetting(KeyValuePair<string, object> settings, Type type)

{

ConsoleWriter.WriteLine(“AppSettingsManager”,

string.Format(“AppSettingsManager Saving {0}”,

settings.Key));

 

try

{

string windowFileName = string.Format(“{0}_ApplicationSettings.xml”,

settings.Key);

 

//Attempt to open or create WindowSettings file

using (IsolatedStorageFile storageFile = GetIsolatedStorageFile())

{

using (IsolatedStorageFileStream fileStream =

new IsolatedStorageFileStream(windowFileName,

System.IO.FileMode.Create,

storageFile))

{

using (TextWriter writer = new StreamWriter(fileStream))

{

XmlSerializer serializer = new XmlSerializer(type);

serializer.Serialize(writer, (object)settings.Value);

writer.Flush();

writer.Close();

}

}

}

}

catch (FileNotFoundException)

{

//File hasn’t been created yet, use defaults.

throw;

}

catch (InvalidOperationException)

{

//Cannot serialize this object

throw;

}

}

 

public static KeyValuePair<string, object> GetSetting(string settingName, Type type)

{

ConsoleWriter.WriteLine(“AppSettingsManager”,

string.Format(“AppSettingsManager Accessing {0}”,

settingName));

try

{

string windowFileName = string.Format(“{0}_ApplicationSettings.xml”,

settingName);

 

//Attempt to open or create WindowSettings file

using (IsolatedStorageFile storageFile = GetIsolatedStorageFile())

{

using (IsolatedStorageFileStream fileStream =

new IsolatedStorageFileStream(windowFileName,

System.IO.FileMode.Open,

storageFile))

{

using (TextReader reader = new StreamReader(fileStream))

{

XmlSerializer serializer = new XmlSerializer(type);

object settingValue = serializer.Deserialize(reader);

reader.Close();

return new KeyValuePair<string, object>(settingName,

settingValue);

}

}

}

}

catch (FileNotFoundException)

{

//New file, try to make a default setting.

try

{

//This is an essential type and must be created by the

//database classes.

if (type != typeof(DatabaseConnectionInfo))

{

//Otherwise, reflect a default one

object reflectedSetting = Activator.CreateInstance(type);

return new KeyValuePair<string, object>(settingName,

reflectedSetting);

}

}

catch

{

//Couldn’t create defaults either.

throw;

}

}

catch

{

//Other general exception

throw;

}

 

return new KeyValuePair<string, object>();

}

}

What we can do now is call these methods passing in the settingName and a System.Type which defines the type of data you are storing, and they will be written to isolated storage. The type of Isolated storage file is retrieved using this method :-

private static IsolatedStorageFile GetIsolatedStorageFile()

{

if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)

{

return IsolatedStorageFile.GetUserStoreForApplication();

}

else

{

return IsolatedStorageFile.GetUserStoreForAssembly();

}

}

If you use ClickOnce to deploy your application I found that the settings are lost with each iteration unless you use the UserStoreForApplication, whereas for a normally deployed application the UserStoreForAssembly will be adequate.

Now we can call GetSetting and SaveSetting, passing in the setting name as a string and the type, like this :-

ApplicationSettingsManager.SaveSetting(new KeyValuePair<string, object>(SettingStrings.NumberOfIterations, iterationCountNum.Value), typeof(decimal));

iterationCountNum.Value = (decimal)ApplicationSettingsManager.GetSetting(SettingStrings.NumberOfIterations, typeof(decimal)).Value;

Note that I use a SettingStrings class to store string values for setting names, so that if they need to be changed they are all in one place. In the GetSetting method we return an object, so that needs to be cast as the type we are expecting back for the setting.

That’s about it.. a very useful little utility class.