-1

Question

How can I save "settings" so that they can be used again after the application has been closed?

When I say settings I mean different properties of the controls on my form.

What is the easiest and most appropriate method? I've read you can save to the system registry or a xml file?

Background

I have a form that creates a row in a Table that changes depending on what control is set or change.

I would like to be able to save different configurations and display them in a combobox for repeated use.

Example

  1. The end user fill in all textboxs and ticks checkboxes.
  2. They then click add to favourites
  3. They add a favourite name and save
  4. The save is then permanently visible in the favourites combobox.

My form

enter image description here


Dan Cundy
  • 2,649
  • 2
  • 38
  • 65
  • Save it where? File system? – Black Frog Apr 24 '15 at 21:06
  • 4
    I typed "c# save settings" into Google and got this: [How To: Write User Settings at Run Time with C#](https://msdn.microsoft.com/en-us/library/bb397755%28v=vs.110%29.aspx) – Setsu Apr 24 '15 at 21:07
  • Here is a good MSDN article https://msdn.microsoft.com/en-us/library/aa730869%28v=vs.80%29.aspx – Kevin Apr 24 '15 at 21:08
  • Save the info to a list, serialize it in 3 lines; read it back with 3 more – Ňɏssa Pøngjǣrdenlarp Apr 24 '15 at 21:11
  • @MethodMan, forgive me for using the site as how it was designed. I have done my research the topic and prefer to ask questions and engage in conversation with other people, rather than following tutorials. But to answer your question, Google works fine in my browser. – Dan Cundy Apr 24 '15 at 21:31
  • the best way to lean is by doing and if someone were to post a workable solution.. wouldn't that in effect be the same as a `Tutorial` if you look deeper into my question than what's posted than sorry.. however this is not a code factory site either.. not to mention that this is one of those questions that's primarily opinionated in regards to there are many ways to skin this cat – MethodMan Apr 24 '15 at 21:32
  • I wasn't asking for a code snippet. Now I know the different ways to achieve my end goal I will now have to further research and finally implement. I can see what you are saying but a tailored solution to a question that directly relates to your project beats a generic tutorial any day. – Dan Cundy Apr 24 '15 at 21:39
  • 1
    I disagree with your justification. MSDN tutorials were written to make the official documentation more palatable to newcomers of the language; it is _exactly_ what you should have read. If you had a question reading those tutorials then that would be fair game, but out right stating that you can't be bothered to read them is not the attitude a programmer should have. Furthermore, did you even check this site? There are already questions that deal with your specific issue already, like [this](http://stackoverflow.com/questions/453161), or [this](http://stackoverflow.com/questions/14616958). – Setsu Apr 25 '15 at 01:10

3 Answers3

2

There are many ways to do this. But in all these options, you need to store the users selection somewhere. You can store this in

  1. A database table, associate the setting with a unique user ID, like LoginID
  2. A Preferences XML file : Refer this
  3. As a Setting in your project : Refer this
  4. As a Registry Entry : Refer this
  5. An INI File

You might want to take a look at Persisting Application Settings in the .NET Framework

Community
  • 1
  • 1
Saagar Elias Jacky
  • 2,684
  • 2
  • 14
  • 28
  • Note: I specifically left registry entries out of my answer. Not that it isn't an option, just consider all the reasons it's not a good idea: http://stackoverflow.com/questions/2600161/why-arent-net-application-settings-stored-in-the-registry – maplemale Apr 24 '15 at 21:22
  • 2
    @maplemale completely agree... just wanted to put all options in the desk... – Saagar Elias Jacky Apr 24 '15 at 21:23
1

It depends on your application and what it's used for and its architecture.

There are multiple options:

  1. You could save it in a database. This option is nice when there are a lot of settings and especially nice in a multi-user platform. If this is a client server application, this may also be preferable for that reason. If you want to keep this simple and don't see user settings getting complex / having very many, this may not be the best option.

  2. You could save it in a flat file. This option is similar to the first, but likely better in the case where your application is more stand-alone and/or you just don't have any other benefit of having those settings on a server.

  3. You could store them in your Applications Settings. There is a good answer regarding how to do that here: https://msdn.microsoft.com/en-us/library/0zszyc6e%28v=vs.110%29.aspx

Another thing to consider is how you want to load those settings. For windows forms development, having classes which define your layout and binding to those classes can be useful. Therefore, you may want to store this data in XML which can be easily serialized directly into a class which defines what your form looks like. You would be able to store that XML anywhere really: Locally or on the server in a database.

maplemale
  • 2,006
  • 21
  • 35
1

One way you could save the data would be to write it to the registry, under the HKCU node. This way different users of your application will have their own settings even if the app is on the same machine. It also keeps the file system a little cleaner and doesn't require a database. But the downside is that the favorites only live on the machine, and don't roam with the user across devices.

A way to implement this would be to wrap your form settings in a class that knows how to save and load values from the registry. This, along with a registry helper class, could make it pretty easy to add "Favorites" functionality to your form.

For example, you could first create a Registry helper class that will read and write settings to the HKCU node (so the settings are specific to the logged in user):

public class RegHelper
{
    private static readonly RegistryKey Root = Registry.CurrentUser
        .CreateSubKey(@"Software\CompanyName\ApplicationName");

    private readonly RegistryKey _thisKey = Root;

    public RegHelper() { }

    public RegHelper(string favoriteKey)
    {
        _thisKey = Root.CreateSubKey(favoriteKey);
    }

    public List<string> GetSubKeys()
    {
        return _thisKey.GetSubKeyNames().ToList();
    }

    public void SetProperty(string propertyName, string value)
    {
        _thisKey.SetValue(propertyName, value, RegistryValueKind.String);
    }

    public void SetProperty(string propertyName, bool value)
    {
        SetProperty(propertyName, value.ToString());
    }

    public string GetProperty(string propertyName)
    {
        return GetProperty(propertyName, string.Empty);
    }

    public string GetProperty(string propertyName, string defaultValue)
    {
        return _thisKey.GetValue(propertyName, defaultValue).ToString();
    }

    public bool GetPropertyAsBool(string propertyName)
    {
        return bool.Parse(GetProperty(propertyName, default(bool).ToString()));
    }
}

Then, you could wrap the fields of your form into a class that not only has properties that match your form fields, but also has methods to save the values to the registry and some static methods to load all Favorites or a specific named Favorite. For example:

public class Favorite
{
    public string Name { get; private set; }
    public string Notes { get; set; }
    public bool NotesFromPlanner { get; set; }
    public string Project { get; set; }
    public string DbLocation { get; set; }
    public string AssesmentToolVersion { get; set; }
    public string ProjectCodes { get; set; }
    public bool StraightToNew { get; set; }

    public Favorite(string name)
    {
        this.Name = name;
    }

    public void Save()
    {
        var reg = new RegHelper(this.Name);
        reg.SetProperty("Name", Name);
        reg.SetProperty("Notes", Notes);
        reg.SetProperty("NotesFromPlanner", NotesFromPlanner);
        reg.SetProperty("Project", Project);
        reg.SetProperty("DbLocation", DbLocation);
        reg.SetProperty("AssesmentToolVersion", AssesmentToolVersion);
        reg.SetProperty("ProjectCodes", ProjectCodes);
        reg.SetProperty("StraightToNew", StraightToNew);
    }

    public static Favorite GetFavorite(string favoriteName)
    {
        var reg = new RegHelper(favoriteName);
        return new Favorite(favoriteName)
        {
            Notes = reg.GetProperty("Notes"),
            NotesFromPlanner = reg.GetPropertyAsBool("NotesFromPlanner"),
            Project = reg.GetProperty("Project"),
            DbLocation = reg.GetProperty("DbLocation"),
            AssesmentToolVersion = reg.GetProperty("AssesmentToolVersion"),
            ProjectCodes = reg.GetProperty("ProjectCodes"),
            StraightToNew = reg.GetPropertyAsBool("StraightToNew"),
        };
    }

    public static List<Favorite> GetFavorites()
    {
        return new RegHelper().GetSubKeys().Select(GetFavorite).ToList();
    }

    public override string ToString()
    {
        return this.Name;
    }
}

Then, you could use the Favorite class to populate your Favorites drop down:

private void Form1_Load(object sender, EventArgs e)
{
    // Get all saved favorites and load them up in the combo box
    foreach (var favorite in Favorite.GetFavorites())
    {
        cboFavorites.Items.Add(favorite);
    }
}

Now, when a favorite is picked from the combo box, we want to populate our form with the details:

private void cboFavorites_SelectedIndexChanged(object sender, EventArgs e)
{
    var favorite = (Favorite) cboFavorites.SelectedItem;

    txtNotes.Text = favorite.Notes;
    txtAssetToolVersion.Text = favorite.AssesmentToolVersion;
    txtDbLocation.Text = favorite.DbLocation;
    chkNotesFromPlanner.Checked = favorite.NotesFromPlanner;
    txtProjectCodes.Text = favorite.ProjectCodes;
    cboProjects.Text = favorite.Project;
    chkStraightToNew.Checked = favorite.StraightToNew;
}

And when someone clicks "Save Favorite", we want to add (or update) the favorite details to the registry:

private void btnAddFavorite_Click(object sender, EventArgs e)
{
    string favoriteName = cboFavorites.Text;

    if (string.IsNullOrEmpty(favoriteName))
    {
        MessageBox.Show("Please type a name for the favorite in the Favorites box.");
        return;
    }

    var favorite = new Favorite(favoriteName)
    {
        Notes = txtNotes.Text,
        AssesmentToolVersion = txtAssetToolVersion.Text,
        DbLocation = txtDbLocation.Text,
        NotesFromPlanner = chkNotesFromPlanner.Checked,
        ProjectCodes = txtProjectCodes.Text,
        Project = cboProjects.Text,
        StraightToNew = chkStraightToNew.Checked
    };

    favorite.Save();

    // When saving a favorite, add it to the combo box
    // (remove the old one first if it already existed)
    var existingFav = cboFavorites.Items.Cast<Favorite>()
        .FirstOrDefault(fav => fav.Name == favoriteName);
    if (existingFav != null)
    {
        cboFavorites.Items.Remove(existingFav);
    }

    cboFavorites.Items.Add(favorite);
    cboFavorites.Text = favoriteName;
}

This should be enough to get you started, if you want to go the registry route.

Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • You can achieve all of the benefits you list and avoid the limitations by simply using _AppData\Roaming_. This was specifically designed for programs to dump their settings, and the average user doesn't care because they don't see it by default. – Setsu Apr 25 '15 at 00:52
  • This would be perfect if it was using xml or a way that all users could use the same settings. Using the reg is extremely limiting for my project. – Dan Cundy Apr 30 '15 at 20:14