Introduction
Saving and restoring preferences wasn't made easy in C#, and the multitude of solutions found both here and elsewhere on the Internet aren't flexible enough to handle preferences for a large application with complicated user interface elements and mediation objects. The solution I've come up with is generic enough to satisfy my needs and hopefully, with slight modification, yours as well. The fact you're reading this tells me you've run into the same problems that I have and need an answer pronto.
Using the Code
Using the code is quite simple. As I said, it's generic enough to do just about anything so long as you're prepared for its usage.
Since most preference work is done in UI elements (forms, etc.), I'll approach the examples from the standpoint of the "Worlds Most Simple Form (tm)".
If you've been doing UI for a while and are worth your snuff, you know you should be operating off a baseform of some kind. Here is what you'll need to have in your form:
public String PrefsToSave { get { return "Left,Top,Width,Height"; } }
PrefsToSave
is the variable I picked for the demonstration (and subsequent implementation of our UI), but you can name it whatever you want. I'm sure you'll be modifying the preference code anyway.
Here's the rest of your form implementation to utilize the preferences:
private void Form1_Load( object sender, EventArgs e ) {
PrefsModule.Prefs.RestorePrefs( this );
}
private void Form1_FormClosing( object sender, FormClosingEventArgs e ) {
PrefsModule.Prefs.SavePrefs( this );
}
Bind your form Load
and FormClosing
events and place the calls to the preference module. You're done with the form, now onto the preference code.
I won't go into a ton of detail here (I've commented practically every line of code including XML commentary), but just to explain how everything links together...
static private String GetPrefString( object o ) {
PropertyInfo[] pi = o.GetType().GetProperties();
for( int i=0; i<pi.Length; i++ ){
if( pi[ i ].Name == "PrefsToSave" ) {
return pi[ i ].GetValue( o, null ).ToString();
}
}
return "";
}
GetPrefString
is called inside the preference handler and retrieves that PrefsToSave
variable you created in the form. If you'd like to change the name of the public
property, you'll also need to modify it here:
static public bool SavePrefs( object o ) {
String sFile = GetPrefFileName( o );
List<String> prefList = StringToList( GetPrefString( o ), ',' );
String sPrefText = "";
if( prefList.Count > 0 ) {
for( int pref = 0; pref<prefList.Count; pref++ ){
sPrefText += prefList[ pref ] + " = " +
GetValueFor( o, prefList[ pref ] ) + "\n";
}
if( sPrefText.Length > 0 ) {
if( File.Exists( sFile ) ) {
File.Delete( sFile );
}
File.WriteAllText( sFile, sPrefText.ToString() );
}
return true;
}
return false;
}
Here we utilize the GetPrefString
function (among others) to retrieve the property settings from your object based on the items listed in the PrefsToSave
property. These settings are formed up into a string
and written to [object name].dat in the current directory for your application.
You may want to modify how and where preferences are stored. I plan on making this save all preference files to a prefs directory under the application. One other extension I'd considered is storing each objects preferences to an XML file, but for now I'm keeping it simple.
Points of Interest
I'm a bit baffled by the lack of an example using the .NET objects that I stumbled onto coming up with this solution, but like all else, you don't know it till you try it.
The solution included in the download runs as is (though you may want to recompile to try it out). After running, just place the form at any random location on the screen and close it. Run the application again and the file should appear at the same spot.
Stability
This is a recent (as in yesterday) creation of mine so I have not tested this for all possible circumstances. You should be able to create some other properties in the test form, add these property names to the PrefsToSave
property and run it, having that property successfully restored.
Final Word
If you end up using this in your application, I'd appreciate a source of origin statement but I don't demand it - that's why I've left it out of the sample code. I'd also appreciate a comment below just to let me know you've found it useful. Thanks.
History
- 4/3/2007: Initial creation and upload
I have been employed by American Innovations (www.amerinnovations.com) for roughly 8 years comprising work in both desktop and handheld application development. The large majority of my work involves user interface with a strong emphasis on middle tier and mediation objects in heavy OOP environments.
Known development languages and technologies: Visual Foxpro 7/9, Clipper, C# in .Net 1.1 and 2.0, ASP, ASPx, HTML, Javascript, SQL 2000 and 2003, Photoshop, and 3d Studio Max.