Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a collection of a custom class to Settings.Settings

I've been having a helluva time trying to add a custom collection of a custom class to the application settings of my winforms project I feel like Ive tried it about six different ways, including this way, this way, this way, and this way but nothing seems to work...

Currently the code complies, and runs fine - no exceptions anywhere. Code his the Save function but no entries are created in the settings xml file (I have a few other settings and it works for all of them but this one FYI). When it loads, Properties.Settings.Default.LastSearches is always null... Any thoughts?

Heres my current code:

The Classes:

[Serializable]
public class LastSearch : ISerializable
{
    public DateTime Date { get; set; }
    public string Hour { get; set; }
    public string Log { get; set; }
    public string Command { get; set; }
    public List<string> SelectedFilters { get; set; }
    public List<string> SearchTerms { get; set; }
    public List<string> HighlightedTerms { get; set; }
    public List<string> ExcludedTerms { get; set; }

    public LastSearch(DateTime date, string hour, string log, string command, List<string> selectedFilters,
        List<string> searchTerms, List<string> highlightedTerms, List<string> excludedTerms)
    {
        Date = date.ToUniversalTime();
        Hour = hour;
        Log = log;
        Command = command;
        SelectedFilters = selectedFilters;
        SearchTerms = searchTerms;
        HighlightedTerms = highlightedTerms;
        ExcludedTerms = excludedTerms;
    }

    protected LastSearch(SerializationInfo info, StreamingContext context)
    {
        Date = info.GetDateTime("Date");
        Hour = info.GetString("Hour");
        Log = info.GetString("Log");
        Command = info.GetString("Command");
        SelectedFilters = (List<string>)info.GetValue("SelectedFilters", typeof(List<string>));
        SearchTerms = (List<string>)info.GetValue("SearchTerms", typeof(List<string>));
        HighlightedTerms = (List<string>)info.GetValue("HighlightedTerms", typeof(List<string>));
        ExcludedTerms = (List<string>)info.GetValue("ExcludedTerms", typeof(List<string>));
    }
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Date", Date);
        info.AddValue("Hour", Hour);
        info.AddValue("Log", Log);
        info.AddValue("Command", Command);
        info.AddValue("SelectedFilters", SelectedFilters);
        info.AddValue("SearchTerms", SearchTerms);
        info.AddValue("HighlightedTerms", HighlightedTerms);
        info.AddValue("ExcludedTerms", ExcludedTerms);
    }
}

[Serializable]
public class LastSearchCollection : ISerializable
{
    public List<LastSearch> Searches { get; set; }

    public LastSearchCollection()
    {
        Searches = new List<LastSearch>();
    }

    public LastSearchCollection(SerializationInfo info, StreamingContext ctxt)
    {
        Searches = (List<LastSearch>)info.GetValue("LastSearches", typeof(List<LastSearch>));
    }
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Searches", Searches);
    }
}

Writing to Settings:

if (RecentQueriesToolStripMenuItem.DropDownItems.Count > 0)
{
    // Last Search Settings
    if (Properties.Settings.Default.LastSearches == null)
        Properties.Settings.Default.LastSearches = new LastSearchCollection();

    Properties.Settings.Default.LastSearches.Searches.Clear();
    foreach (LastSearchMenuItem item in RecentQueriesToolStripMenuItem.DropDownItems)
    {
        Properties.Settings.Default.LastSearches.Searches.Add(item.SearchData);
    }
}

// Save all settings
Properties.Settings.Default.Save();

Loading from setttings

// Last Searches
if (Properties.Settings.Default.LastSearches != null)
{
    int i = 0;
    foreach (LastSearch search in Properties.Settings.Default.LastSearches.Searches)
    {
        LastSearchMenuItem searchMenuItem = new LastSearchMenuItem(search);
        RecentQueriesToolStripMenuItem.DropDownItems.Add(searchMenuItem);
        RecentQueriesToolStripMenuItem.DropDownItems[i].Click += new EventHandler(RecentSearch_Click);
        i++;
    }
}
like image 541
Hershizer33 Avatar asked Aug 09 '11 17:08

Hershizer33


1 Answers

After more than 8 years i had the same need that you had. I solved it using XML Serialization to store the custom collection in the user settings.

Here is an example adopted to your code.

First of all you need to set the type of your setting to the type of your collection class (e.g. "MyProject.LastSearchCollection"). See Why am I unable to select a custom Type for a setting from the same project/assembly as the settings file? on how to do this. If Visual Studio says it can't find your custom class, make sure the class is public and has a public, parameterless constructor.

The custom class:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Runtime.Serialization;

namespace MyProject
{
    [SettingsSerializeAs(SettingsSerializeAs.Xml)]
    public class LastSearch
    {
        public DateTime Date { get; set; }
        public string Hour { get; set; }
        public string Log { get; set; }
        public string Command { get; set; }
        public List<string> SelectedFilters { get; set; }
        public List<string> SearchTerms { get; set; }
        public List<string> HighlightedTerms { get; set; }
        public List<string> ExcludedTerms { get; set; }

        public LastSearch(DateTime date, string hour, string log, string command, List<string> selectedFilters,
            List<string> searchTerms, List<string> highlightedTerms, List<string> excludedTerms)
        {
            Date = date.ToUniversalTime();
            Hour = hour;
            Log = log;
            Command = command;
            SelectedFilters = selectedFilters;
            SearchTerms = searchTerms;
            HighlightedTerms = highlightedTerms;
            ExcludedTerms = excludedTerms;
        }

        protected LastSearch(SerializationInfo info, StreamingContext context)
        {
            Date = info.GetDateTime("Date");
            Hour = info.GetString("Hour");
            Log = info.GetString("Log");
            Command = info.GetString("Command");
            SelectedFilters = (List<string>)info.GetValue("SelectedFilters", typeof(List<string>));
            SearchTerms = (List<string>)info.GetValue("SearchTerms", typeof(List<string>));
            HighlightedTerms = (List<string>)info.GetValue("HighlightedTerms", typeof(List<string>));
            ExcludedTerms = (List<string>)info.GetValue("ExcludedTerms", typeof(List<string>));
        }
    }

    [SettingsSerializeAs(SettingsSerializeAs.Xml)]
    public class LastSearchCollection
    {
        public List<LastSearch> Searches { get; set; }

        public LastSearchCollection()
        {
            Searches = new List<LastSearch>();
        }

        public LastSearchCollection(SerializationInfo info, StreamingContext ctxt)
        {
            Searches = (List<LastSearch>)info.GetValue("LastSearches", typeof(List<LastSearch>));
        }
    }
}

The only differences are, that i added the [SettingsSerializeAs(SettingsSerializeAs.Xml)] attributes and removed your serialization functions. You may have to add the reference System.Configuration to your project.

Save the settings just like:

LastSearchCollection searches =  new LastSearchCollection();

List<string> selectedFilters = new List<string>();
selectedFilters.Add("Filter1");
selectedFilters.Add("Filter2");
selectedFilters.Add("FilterN");

searches.Searches.Add(new LastSearch(DateTime.Now, "7", "Log1", "CommandA", selectedFilters, new List<string>(), new List<string>(), new List<string>()));
searches.Searches.Add(new LastSearch(DateTime.Now, "9", "Log2", "CommandB", new List<string>(), new List<string>(), new List<string>(), new List<string>()));
Properties.Settings.Default.LastSearches = searches;

// Save all settings
Properties.Settings.Default.Save();

Afterwards the user.config written to disc will look like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
    ...
    </configSections>
    <userSettings>
    ...
        <MyProject.Properties.Settings>
            <setting name="LastSearches" serializeAs="Xml">
                <value>
                    <LastSearchCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <Searches>
                            <LastSearch>
                                <Date>2020-03-01T07:49:44.5512864Z</Date>
                                <Hour>7</Hour>
                                <Log>Log1</Log>
                                <Command>CommandA</Command>
                                <SelectedFilters>
                                    <string>Filter1</string>
                                    <string>Filter2</string>
                                    <string>FilterN</string>
                                </SelectedFilters>
                                <SearchTerms />
                                <HighlightedTerms />
                                <ExcludedTerms />
                            </LastSearch>
                            <LastSearch>
                                <Date>2020-03-01T07:49:44.5562864Z</Date>
                                <Hour>9</Hour>
                                <Log>Log2</Log>
                                <Command>CommandB</Command>
                                <SelectedFilters />
                                <SearchTerms />
                                <HighlightedTerms />
                                <ExcludedTerms />
                            </LastSearch>
                        </Searches>
                    </LastSearchCollection>
                </value>
            </setting>
        </MyProject.Properties.Settings>
    </userSettings>
</configuration>
like image 164
Yosh Avatar answered Oct 15 '22 14:10

Yosh