Saving settings in the language selection form
Someone recently sent me an error message from the language selection form, which uses Isolated Storage to save its settings. The file in which the settings are stored appeared to be locked by another process.
I have no idea why the file was locked, but my instinct is to throw out the isolated storage completely.
This code is at least 10 years old and back then isolated storage was recommended for saving user settings. I always thought it was too complicated, but I wanted to do it in a .NET way in the brave new .NET world.
It is now very easy to save user settings, if you add them via the project properties in Visual Studio. This is how you could change the code:
The following example is for C# in a WPF project, but it is more or less the same in VB and probably identical for a Windows Forms application.
Add two settings
- LanguageStartupMode, as an Integer with the default value 2. This value means that the dialog will be shown at program startup.
(Do not use the default value of 0, because this means that the form will not appear, even the first time that the program is started.) - SelectedLanguage as a string.
Change the LoadSettings() function
This code is in the file SelectLanguage.cs or SelectLanguage.xaml.cs.
Replace this old code
| Old code | private void LoadSettings()
{
// Set the defaults
StartupMode = enumStartupMode.ShowDialog;
SelectedCulture = Thread.CurrentThread.CurrentUICulture;
// Create an IsolatedStorageFile object and get the store
// for this application.
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForDomain ();
// Check whether the file exists
if ( isoStorage.GetFileNames ( "CultureSettings.xml" ).Length > 0 ) //MLHIDE
{
// Create isoStorage StreamReader.
StreamReader stmReader = new StreamReader
( new IsolatedStorageFileStream
( "CultureSettings.xml",
FileMode.Open,
isoStorage ) ); //MLHIDE
XmlTextReader xmlReader = new XmlTextReader ( stmReader );
// Loop through the XML file until all Nodes have been read and processed.
while ( xmlReader.Read () )
{
switch ( xmlReader.Name )
{
case "StartupMode": //MLHIDE
StartupMode = (enumStartupMode)int.Parse ( xmlReader.ReadString () );
break;
case "Culture": //MLHIDE
string CultName = xmlReader.ReadString ();
CultureInfo CultInfo = new CultureInfo ( CultName );
SelectedCulture = CultInfo;
break;
}
}
// Close the reader
xmlReader.Close ();
stmReader.Close ();
}
isoStorage.Close ();
}
|
| New Code | private void LoadSettings()
{
// I don't think this should throw an exception
int Mode = WpfApplication2.Properties.Settings.Default.LanguageStartupMode ;
string CultName = WpfApplication2.Properties.Settings.Default.SelectedLanguage ;
// Validate the enum
if ( enumStartupMode.IsDefined ( typeof(enumStartupMode), Mode ) )
StartupMode = (enumStartupMode)Mode ;
else
StartupMode = enumStartupMode.ShowDialog ;
// Validate the language with try/catch
try
{
SelectedCulture = new CultureInfo ( CultName ) ;
}
catch ( System.Exception e )
{
SelectedCulture = Thread.CurrentThread.CurrentUICulture;
}
} |
Replace WpfApplication2 with the namespace of your application.
Change the SaveSettings() function
Replace this old code
| Old code | private void SaveSettings()
{
// Get an isolated store for user, domain, and assembly and put it into
// an IsolatedStorageFile object.
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForDomain ();
// Create isoStorage StreamWriter and assign it to an XmlTextWriter variable.
IsolatedStorageFileStream stmWriter = new IsolatedStorageFileStream ( "CultureSettings.xml", FileMode.Create, isoStorage ); //MLHIDE
XmlTextWriter writer = new XmlTextWriter ( stmWriter, Encoding.UTF8 );
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument ();
writer.WriteStartElement ( "CultureSettings" ); //MLHIDE
writer.WriteStartElement ( "StartupMode" ); //MLHIDE
writer.WriteString ( ( (int)StartupMode ).ToString () );
writer.WriteEndElement ();
writer.WriteStartElement ( "Culture" ); //MLHIDE
writer.WriteString ( SelectedCulture.Name );
writer.WriteEndElement ();
writer.WriteEndElement ();
writer.Flush ();
writer.Close ();
stmWriter.Close ();
isoStorage.Close ();
}
|
| New Code | private void SaveSettings()
{
WpfApplication2.Properties.Settings.Default.LanguageStartupMode = (int)StartupMode ;
WpfApplication2.Properties.Settings.Default.SelectedLanguage = SelectedCulture.Name ;
WpfApplication2.Properties.Settings.Default.Save() ;
} |
Replace WpfApplication2 with the namespace of your application.
I think you will agree that this code is simpler than the original version using isolated storage.
To be honest, I don't know whether there could still be a file access problem reading the settings. If there is, then it would be a problem in Microsoft's code.
At present, I have not changed the template file. I might do this in a future version, but first I will have to figure out how to add the user settings automatically.
Phil