Paul
Paul

Reputation:

c#: Create new settings at run time

c# windows forms: How do you create new settings at run time so that they are permanently saved as Settings.Default.-- values?

Upvotes: 24

Views: 42872

Answers (8)

Girl Spider
Girl Spider

Reputation: 350

It took me a long time using the top two answers here plus this link (Create new settings on runtime and read after restart) to get it to finally work.

First of all, set your expectations. The answer here will create a new user setting and you can get its value the next time you launch your app. However, the setting you created this way will not appear in the Settings designer. In fact, when you relaunch the app and try to access the setting in your code, it will not find it. However, the setting you have created through code is saved in the user.config file (say jDoe.config) somewhere in your file system. For you to access this value, you have to add the setting again.

Here is a working example I have:

        private void FormPersistence_Load(object sender, EventArgs e)
        {
            StartPosition = FormStartPosition.Manual;
            // Set window location
            var exists = Settings.Default.Properties.OfType<SettingsProperty>().Any(p => p.Name == Name + "Location");
            if (exists)
            {
                this.Location = (Point)Settings.Default[Name + "Location"];
            }
            else
            {
                var property = new SettingsProperty(Settings.Default.Properties["baseLocation"]);
                property.Name = Name + "Location";
                Settings.Default.Properties.Add(property);
                Settings.Default.Reload();
                this.Location = (Point)Settings.Default[Name + "Location"];
            }
        }

Note: My new setting's name will be resolved at run time. Name is really this.Name, which is the form's name. This is a base form that other forms can inherit from, so all the child forms will be able to remember their locations.
baseLocation is a setting I have manually created in Settings designer. The new setting I have is the same type. This way I don't have to worry about things like provider, type, etc. in code.

Upvotes: 1

Drew Ogle
Drew Ogle

Reputation: 489

In addition to John's solution for saving, the proper method for loading is add the property, and then do a Reload() on your settings.

Your dynamic setting will be there!

For a full example, valid for using in library code, as you can pass the settings in ..

ApplicationSettingsBase settings = passed_in;
SettingsProvider sp = settings.Providers["LocalFileSettingsProvider"];
SettingsProperty p = new SettingsProperty("your_prop_name");
your_class conf = null;
p.PropertyType = typeof( your_class );
p.Attributes.Add(typeof(UserScopedSettingAttribute),new UserScopedSettingAttribute());
p.Provider = sp;
p.SerializeAs = SettingsSerializeAs.Xml;
SettingsPropertyValue v = new SettingsPropertyValue( p );
settings.Properties.Add( p );

settings.Reload();
conf = (your_class)settings["your_prop_name"];
if( conf == null )
{
   settings["your_prop_name"] = conf = new your_class();
   settings.Save();
}

Upvotes: 15

RICK
RICK

Reputation:

What you could do is create a new registry key. Name the new key "Your program settings".

RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software", true);
ProgSettings.CreateSubKey("Your Program settings");    
ProgSettings.Close();

Now you can add String Identifiers and values.

RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software\\Your Program settings", true);
ProgSettings.SetValue("Setting Name", value); // store settings    
string settings = ProgSettings.GetValue("Setting Name", false); // retreave settings    
ProgSettings.DeleteValue("Setting Name", false);

Besure to close the registry key when you are done to avoid conflicts with other parts of your program that may write to the registry.

Many comercial software applications use these methods. stackoverflow has many examples about writing and reading to the registry. This is much easyer then modifying the appconfig.xml file that is used when you create settings.

Upvotes: 1

John
John

Reputation: 232

Just in case that still matters to anyone:

You can dynamically add settings through Settings.Default.Properties.Add(...) and have these also persisted in the local storage after saving (I had those entries reflected in the roaming file).

Nevertheless it seems that the dynamically added settings keep missing in the Settings.Default.Properties collecion after loading again.

I could work around this problem by adding the dynamic property before first accessing it. Example (notice that I "create" my dynamic setting from a base setting):

// create new setting from a base setting:
var property = new SettingsProperty(Settings.Default.Properties["<baseSetting>"]);
property.Name = "<dynamicSettingName>";
Settings.Default.Properties.Add(property);
// will have the stored value:
var dynamicSetting = Settings.Default["<dynamicSettingName>"];

I don't know if this is supported by Microsoft as the documentation is very rare on this topic.

Problem is also described here http://www.vbdotnetforums.com/vb-net-general-discussion/29805-my-settings-run-time-added-properties-dont-save.html#post88152 with some solution offered here http://msdn.microsoft.com/en-us/library/saa62613(v=VS.100).aspx (see Community Content - headline "How to Create / Save / Load Dynamic (at Runtime) Settings"). But this is VB.NET.

Upvotes: 20

Tom Wilson
Tom Wilson

Reputation: 21

You can't add settings directly (at least not without editing the config XML at runtime), but you can fake it.

In my case, I had a group of identical custom controls on the form, and I wanted to store the runtime state of each control. I needed to store the state of each control, since each one had different data it.

I created a new StringCollection setting named ControlData and placed my own data in there. I then load the data from that list and use it to initialize my controls.

The list looks like this:

Box1Text=A
Box1List=abc;def;foo;bar;
Box2Text=hello
Box2List=server1;server2;

In my startup code, I read through the key/value pairs like this:

foreach (string item in Properties.Settings.Default.ControlData) {
  string[] parts=item.split('=');

parts[0] will have the key and parts[1] will have the value. You can now do stuff based on this data.

During the shutdown phase, I do the inverse to write the data back to the list. (Iterate through all the controls in the form and add their settings to ControlData.

Upvotes: 2

Chris Marasti-Georg
Chris Marasti-Georg

Reputation: 34650

How would you access the new settings that you have created? The point of the Visual Studio settings designer is that you can write code that uses these settings with compile-time checking of your code. If you want to dynamically create new settings for your app to use, you will also need to dynamically load them. For dynamic settings, you may want to look at the System.Configuration assembly, notably ConfigurationSection. You can create a custom configuration section with that, which you could use for dynamic setting addition/removal. You might use a ConfigurationCollection for that dynamic addition/removal.

INI files eh? Google turned up this INI library for .NET.

Upvotes: 1

OregonGhost
OregonGhost

Reputation: 23759

Since the Settings class is generated at build time (or, actually, whenever you update the settings file from within the designer), you can't use this mechanism for dynamic scenarios. You can, however, add some collection or dictionary to the application settings and modify that dynamically.

Upvotes: 8

Paul
Paul

Reputation:

I see how what I wanted was the wrong idea. I'm porting a c++ app over to c# and it has a lot of ini file settings and I was looking for a shortcut to add them in. I'm lazy.

Upvotes: 0

Related Questions