Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I save a custom class to user settings using ApplicationSettingsBase?

I'm trying to save a custom class to user settings but not having much success.

I've created a test project in Visual Studio 2010 with Target framework = ".NET Framework 4". The main Form has two text boxes for displaying and editing a plain test string and the "Title" field from my custom class; together with two buttons to Load and Save the settings.

Finally, I added two settings "TestString" (a plain string value) and TestData (type of MyDataClass - I did this in the project's Properties.Settings tab by selecting "Browse..." from the Type dropdown list then manually entering "MyUserSettingsTest.MyDataClass" in the "Selected Type" box as it didn't originally appear in the available type list but then subsequently it does .)

On starting the application and clicking LoadSettings the event handler loads the plain string and MyData or, if this fails, creates a new instance of MyDataClass. I can then edit the plain string and test data Title on the form and click SaveSettings. If I then re-edit the values click LoadSettings again the last saved values are restored as expected for both values. So far so good.

The problem is that on exiting the application and re-starting it the plain test string is restored ok but MyData object isn't! Obviously, the code is persisting MyData to memory ok but not to the permanent store?

The main form code is:

using System;
using System.Windows.Forms;

namespace MyUserSettingsTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public MyDataClass MyData {get;set;}

        private void loadSettingsButton_Click(object sender, EventArgs e)
        {
            this.myTextBox.Text = Properties.Settings.Default.TestString;
            this.MyData = Properties.Settings.Default.TestData;

            if (this.MyData == null)
            {
                this.MyData = new MyDataClass() { ID = 1, Title = "Default New Title" };
            }

            this.myDataTitleTextBox.Text = this.MyData.Title;
        }

        private void saveSettingsButton_Click(object sender, EventArgs e)
        {
            this.MyData.Title = this.myDataTitleTextBox.Text;

            Properties.Settings.Default.TestString = this.myTextBox.Text;
            Properties.Settings.Default.TestData = this.MyData;
            Properties.Settings.Default.Save();
        }
    }
}

My test data class code is:

using System.Configuration;

namespace MyUserSettingsTest
{
    public class MyDataClass : ApplicationSettingsBase
    {
        public MyDataClass()
        {
        }

        private int _id;
        private string _title;

        [UserScopedSetting()]
        [SettingsSerializeAs(SettingsSerializeAs.Xml)] 
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        [UserScopedSetting()]
        [SettingsSerializeAs(SettingsSerializeAs.Xml)] 
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }
    }
}

I don't know if it's of help but the auto-generated app.config file (which contains the setting for TestString but NOT TestData!!?) is:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <section name="MyUserSettingsTest.Properties.Settings"     type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
        </sectionGroup>
    </configSections>
    <userSettings>
        <MyUserSettingsTest.Properties.Settings>
            <setting name="TestString" serializeAs="String">
                <value/>
            </setting>
        </MyUserSettingsTest.Properties.Settings>
    </userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

The auto-generated Settings.Designer.cs file is:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.269
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace MyUserSettingsTest.Properties {


[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

    private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

    public static Settings Default {
        get {
            return defaultInstance;
        }
    }

    [global::System.Configuration.UserScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.DefaultSettingValueAttribute("")]
    public string TestString {
        get {
            return ((string)(this["TestString"]));
        }
        set {
            this["TestString"] = value;
        }
    }

    [global::System.Configuration.UserScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public global::MyUserSettingsTest.MyDataClass TestData {
        get {
            return ((global::MyUserSettingsTest.MyDataClass)(this["TestData"]));
        }
        set {
            this["TestData"] = value;
        }
    }
}
}

Please can anyone tell me what I'm doing wrong or what extra I need to do to get my custom class to persist to user settings properly.

like image 607
user1460663 Avatar asked Jun 16 '12 13:06

user1460663


1 Answers

Save your custom object as a serialized string. Then you only need to store a string. For example, use the Json .NET JsonConverter to serialize and deserialize objects.

Properties.Settings.Default.TestData = JsonConvert.SerializeObject<MyDataClass>(this.MyData);

Then you could read it back like this

this.MyData = JsonConvert.DeserializeObject<MyDataClass>(Properties.Settings.Default.TestData);
like image 147
Shahzad Qureshi Avatar answered Nov 16 '22 14:11

Shahzad Qureshi