Search code examples
c#.netwinformssettings.settingsstringdictionary

Application setting is not saved


I want to save a StringDictionary into the Application Settings in order to fill my listbox lbc_lastCustomersVisited with saved values at application launch.

Here is my application setting (XML format) :

<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Wibe_EFI.Properties" GeneratedClassName="Settings">
    <Profiles />
    <Settings>
        <Setting Name="ApplicationSkinName" Type="System.String" Scope="User">
            <Value Profile="(Default)" />
        </Setting>
        <Setting Name="LastTimeWibeDataObtained" Type="System.String" Scope="User">
            <Value Profile="(Default)" />
        </Setting>
        <Setting Name="LastVisitedCustomer" Type="System.Collections.Specialized.StringDictionary" Scope="User">
            <Value Profile="(Default)" />
        </Setting>
  </Settings>


In my form, I got a StringDictionary local variable :

public partial class MainForm : XtraForm
{
    private StringDictionary lastVisitedCustomers = new StringDictionary();
    [...]
}


Here is how I fill my StringDictionary local variable :

private void btn_selectCustomer_Click(object sender, EventArgs e)
{
    DataRowView selectedRow = GetCustomersGridSelectedRow();
    lastVisitedCustomers.Add(GetCustomerID(selectedRow), String.Format("{0} - {1}", GetCustomerName(selectedRow), GetCustomerCity(selectedRow)));
}

(the StringDictionary is successfully filled)

At FormClosing, I save my setting :

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
        Settings.Default["ApplicationSkinName"] = UserLookAndFeel.Default.SkinName;
        Settings.Default.LastVisitedCustomer = lastVisitedCustomers;
        Settings.Default.Save();
}

The setting ApplicationSkinName is successfully saved but not the lastVisitedCustomer StringDictionary. Because when I load my settings at application launch time, Settings.Default.LastVisitedCustomer is null.


Here is how I load my setting about the application skin (it works) :

public MainForm()
{
        InitializeComponent();
        InitSkinGallery();
        UserLookAndFeel.Default.SkinName = Settings.Default["ApplicationSkinName"].ToString();
}

But I cannot load my StringDictionnary right here because of a NullReferenceException.
So I load it here :

private void MainForm_Load(object sender, EventArgs e)
{
    _mySqlCeEngine = new MySqlCeEngine(this);
    ShowHomePanel();
    LoadLastVisitedCustomers();
}

private void LoadLastVisitedCustomers()
{
    if (Settings.Default.LastVisitedCustomer.Count > 0)
    {
        lastVisitedCustomers = Settings.Default.LastVisitedCustomer;
    }
    lbc_lastCustomersVisited.DataSource = new BindingSource(lastVisitedCustomers, null);
    lbc_lastCustomersVisited.DisplayMember = "Value";
    lbc_lastCustomersVisited.ValueMember = "Key";
}

But at this moment, Settings.Default.LastVisitedCustomer is null and I don't understand why. I tried some things like not using a local variable and read/write directly from Settings.Default.LastVisitedCustomer but I got the same problem.

Thanks,

Hellcat.

EDIT : Added full Settings.settings file (XML view)


Solution

  • I could not find any solution to store a Dictionary in the app settings so I decided to deal with a string and split it :

    public partial class MainForm : XtraForm
    {
        private Dictionary<string, string> lastVisitedCustomers;
    
        public MainForm()
        {
            InitializeComponent();
            InitSkinGallery();
            UserLookAndFeel.Default.SkinName = Settings.Default["ApplicationSkinName"].ToString();
            lastVisitedCustomers = StringToDictionary(Settings.Default["LastVisitedCustomer"].ToString());
        }
    
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Settings.Default["ApplicationSkinName"] = UserLookAndFeel.Default.SkinName;
            Settings.Default["LastVisitedCustomer"] = DictionaryToString(lastVisitedCustomers);
            Settings.Default.Save();
        }
    
        #region Dictionary management
    
        private string DictionaryToString(Dictionary<string, string> dic)
        {
            if (dic.Count == 0)
            {
                return string.Empty;
            }
            else
            {
                string dicString = string.Empty;
                int i = 0;
                foreach (KeyValuePair<string, string> entry in dic)
                {
                    if (i == 0)
                    {
                        dicString = String.Format("{0} ## {1}", entry.Key, entry.Value);
                        i++;
                    }
                    else
                    {
                        dicString += String.Format(" -- {0} ## {1}", entry.Key, entry.Value);
                    }
                }
                return dicString;
            }
        }
    
        private Dictionary<string, string> StringToDictionary(string str)
        {
            Dictionary<string, string> dic = new Dictionary<string,string>();
            if (String.IsNullOrEmpty(str))
            {
                return dic;
            }
            else
            {
                string[] entries = Regex.Split(str, " -- ");
    
                foreach (string entry in entries)
                {
                    string[] kvp = Regex.Split(entry, " ## ");
                    dic.Add(kvp[0], kvp[1]);
                }
    
                return dic;
            }
        }
    }
        #endregion
    

    For now, it works.
    I hope it will helps anyone in my situation.

    Notice : You may have to modify my dictionary methods in order to handle every cases for Exceptions. But I think this is okay now.

    Sorry for any english mistakes