C # - approach for saving user settings in a WPF application?

What approach do you recommend for saving user settings in a WPF windows application (desktop)? Note that the idea is that the user can change their settings at runtime, and then can close the application, and then when the application starts, the application will use the current settings later. Effectively then it will look as if the application settings have not changed.

Q1 - Database or other approach? I have a sqlite database that I will use anyway, so using a table in a database would be as good as any approach?

Q2 - If the database: what is the table of the database tables? One table with columns for different data types that may have (e.g. string , long , DateTime etc.) OR just a table with a row for the value by which you should serialize and de-serialize the values? I think the first would be simpler, and if there arenโ€™t so many settings, thereโ€™s not so much overhead?

Q3 - Can I use the application settings? If so, are there any special tasks needed to ensure perseverance here? Also, what will happen with respect to using the default value in the application settings designer in this case? Will the default value override any settings that were saved between application launches? (or you do not need to use the default value)

+60
c # settings wpf usersettings
Sep 24 '10 at 5:38
source share
9 answers

You can use the Application Settings for this, using a database is not the best option, given the time taken to read and write the settings (especially if you use web services).

Here are some links that explain how to achieve this and use them in WPF -

User Preferences in WPF

WPF quick tip: how to bind to the resources and settings of a WPF application?

Configurable window for WPF

+60
Sep 24 2018-10-10T00:
source share

You can save the settings information as Strings XML in Settings.Default . Create several classes to store configuration data and make sure they are [Serializable] . Then, with the following helpers, you can serialize instances of these objects โ€” either List<T> (or arrays T[] , etc.) of them โ€” up to String . Save each of these lines in its corresponding Settings.Default slot in your WPF Settings application.

To restore objects the next time the application is launched, read the Settings and Deserialize line of interest to the expected type T (which this time should be explicitly specified as an argument of type Deserialize<T> ).

 public static String Serialize<T>(T t) { using (StringWriter sw = new StringWriter()) using (XmlWriter xw = XmlWriter.Create(sw)) { new XmlSerializer(typeof(T)).Serialize(xw, t); return sw.GetStringBuilder().ToString(); } } public static T Deserialize<T>(String s_xml) { using (XmlReader xw = XmlReader.Create(new StringReader(s_xml))) return (T)new XmlSerializer(typeof(T)).Deserialize(xw); } 
+10
Jan 6 2018-12-12T00:
source share

I also prefer to serialize the file. XML files are suitable mainly for all requirements. You can use the ApplicationSettings assembly but they have some limitations and a specific, but (for me) very strange behavior in which they are stored. I used a lot of them and they work. But if you want full control over how and where they are stored, I use a different approach.

  1. Make a class Somewhere with all your settings. I called it MySettings
  2. Implement save and read to save
  3. Use them in your application code

Benefits:

  • A very simple approach.
  • One class for customization. Loading. Save.
  • All your settings are type safe.
  • You can simplify or expand the logic to suit your needs (Versions, many profiles per user, etc.).
  • It works very well anyway (database, WinForms, WPF, Service, etc.)
  • You can determine where to store the XML files.
  • You can find them and manipulate them either with code or a guide
  • It works for any deployment method I can imagine.

Disadvantages: - You have to think about where to store your settings files. (But you can just use your installation folder)

Here is a simple example (not verified) -

 public class MySettings { public string Setting1 { get; set; } public List<string> Setting2 { get; set; } public void Save(string filename) { using (StreamWriter sw = new StreamWriter(filename)) { XmlSerializer xmls = new XmlSerializer(typeof(MySettings)); xmls.Serialize(sw, this); } } public MySettings Read(string filename) { using (StreamReader sw = new StreamReader(filename)) { XmlSerializer xmls = new XmlSerializer(typeof(MySettings)); return xmls.Deserialize(sw) as MySettings; } } } 

And here is how to use it. You can load the default values โ€‹โ€‹or override them using user preferences, just checking if user preferences exist:

 public class MyApplicationLogic { public const string UserSettingsFilename = "settings.xml"; public string _DefaultSettingspath = Assembly.GetEntryAssembly().Location + "\\Settings\\" + UserSettingsFilename; public string _UserSettingsPath = Assembly.GetEntryAssembly().Location + "\\Settings\\UserSettings\\" + UserSettingsFilename; public MyApplicationLogic() { // if default settings exist if (File.Exists(_UserSettingsPath)) this.Settings = Settings.Read(_UserSettingsPath); else this.Settings = Settings.Read(_DefaultSettingspath); } public MySettings Settings { get; private set; } public void SaveUserSettings() { Settings.Save(_UserSettingsPath); } } 

maybe someone is inspired by this approach. This is how I have been doing this for many years now, and I am quite pleased with it.

+9
10 Oct '13 at 9:05
source share

The longest, most typical approach to this issue: Isolated storage.

Serialize your control state in XML or another format (especially easy if you save the dependency properties using WPF), and then save the file to an isolated user repository.

If you want to go along the application setup route, I tried something similar at some point ... although the approach below could easily be adapted to use isolated storage:

 class SettingsManager { public static void LoadSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements) { EnsureProperties(sender, savedElements); foreach (FrameworkElement element in savedElements.Keys) { try { element.SetValue(savedElements[element], Properties.Settings.Default[sender.Name + "." + element.Name]); } catch (Exception ex) { } } } public static void SaveSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements) { EnsureProperties(sender, savedElements); foreach (FrameworkElement element in savedElements.Keys) { Properties.Settings.Default[sender.Name + "." + element.Name] = element.GetValue(savedElements[element]); } Properties.Settings.Default.Save(); } public static void EnsureProperties(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements) { foreach (FrameworkElement element in savedElements.Keys) { bool hasProperty = Properties.Settings.Default.Properties[sender.Name + "." + element.Name] != null; if (!hasProperty) { SettingsAttributeDictionary attributes = new SettingsAttributeDictionary(); UserScopedSettingAttribute attribute = new UserScopedSettingAttribute(); attributes.Add(attribute.GetType(), attribute); SettingsProperty property = new SettingsProperty(sender.Name + "." + element.Name, savedElements[element].DefaultMetadata.DefaultValue.GetType(), Properties.Settings.Default.Providers["LocalFileSettingsProvider"], false, null, SettingsSerializeAs.String, attributes, true, true); Properties.Settings.Default.Properties.Add(property); } } Properties.Settings.Default.Reload(); } } 

..... and ....

  Dictionary<FrameworkElement, DependencyProperty> savedElements = new Dictionary<FrameworkElement, DependencyProperty>(); public Window_Load(object sender, EventArgs e) { savedElements.Add(firstNameText, TextBox.TextProperty); savedElements.Add(lastNameText, TextBox.TextProperty); SettingsManager.LoadSettings(this, savedElements); } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { SettingsManager.SaveSettings(this, savedElements); } 
+6
Sep 24 '10 at 6:05
source share

In addition to the database, you can also have the following options for saving user-related settings.

  • in section HKEY_CURRENT_USER

  • in the AppData folder

  • using the Settings file in WPF and setting its scope as User

+4
Sep 24 '10 at 6:03
source share

In my experience, storing all the settings in a database table is the best solution. Don't even worry about performance. Databases today are fast and can easily store thousands of columns in a table. I learned this difficult path - before I began to serialize / deserialize - a nightmare. Saving it in a local file or in the registry has one big problem: if you need to maintain your application and the computer is turned off - the user is not in front of him - you canโ€™t do anything ... if the settings are in the database, you can change them and viola , not to mention that you can compare settings ....

+3
Dec 13 '11 at 22:34
source share

I usually do these things by defining my own [ Serializable ] settings class and simply serializing it to disk. In your case, you can just save it as a blob string in the SQLite database.

+1
Sep 24 '10 at 7:02
source share
  • In all the places where I worked, the database was mandatory due to application support. As Adam said, the user may not be at his desk, or the machine may be turned off, or you can quickly change someone's configuration or assign a standard configuration (or team member) to a new member.

  • If the settings are likely to grow as new versions of the application are released, you may want to save the data as drops, which can then be deserialized by the application. This is especially useful if you are using something like Prism that detects modules, because you cannot know what settings the module will return. Keys can be entered using the combined username / machine key. Thus, you can have different settings for each machine.

  • I did not use the built-in settings class, so I will not comment. :)

0
Sep 18 '13 at 9:33 on
source share

I wanted to use a class-based xml control file for my WPF desktop application VB.net. The above code to do it all in one, excellent and set me in the right direction. In case someone is looking for a VB.net solution, here is the class I built:

 Imports System.IO Imports System.Xml.Serialization Public Class XControl Private _person_ID As Integer Private _person_UID As Guid 'load from file Public Function XCRead(filename As String) As XControl Using sr As StreamReader = New StreamReader(filename) Dim xmls As New XmlSerializer(GetType(XControl)) Return CType(xmls.Deserialize(sr), XControl) End Using End Function 'save to file Public Sub XCSave(filename As String) Using sw As StreamWriter = New StreamWriter(filename) Dim xmls As New XmlSerializer(GetType(XControl)) xmls.Serialize(sw, Me) End Using End Sub 'all the get/set is below here Public Property Person_ID() As Integer Get Return _person_ID End Get Set(value As Integer) _person_ID = value End Set End Property Public Property Person_UID As Guid Get Return _person_UID End Get Set(value As Guid) _person_UID = value End Set End Property End Class 
0
Feb 21 '16 at 15:23
source share



All Articles