C# Settings File: Why do I have to use Settings.Default? - c#

I'm just wondering why it's Settings.Default.<mysetting> instead of just Settings.<mysetting>?

Simply put: because Settings is a class, and the properties are instance properties. So you need an instance, and the default way of creating an instance is through the Default property.
The obvious followup question is why the properties aren't just static to start with... and I surmise that the answer is that it's useful to be able to create settings in ways other than with the default settings load/save approach... for example, loading them from a database, or from a different file path.

It doesn't make sense to use Settings.Default.CompanyName when Settings.CompanyName can be created as Property returning the instance's value.

Related

What is the difference between Settings.Default.[PropertyName] , Settings.Default.Properties and Settings.Default.PropertyValues?

I wanted to know the difference between these 3 Settings.Default.<PropertyName> , Settings.Default.Properties and Settings.Default.PropertyValues .
I have a wpf window that would dynamically generate controls based on these Settings and then one can update the Settings values
I first used Settings.Default.Properties Collection , but I believe it does not update the values in either config or the physical settings file in the user folder.
So I used reflection to update , But I still couldn't figure how to obtain
values by Reflection . (May still need to research on this)
Settings.Default.GetType().GetProperty(propertyName,
typeof(string)).SetValue(source, fileDialog.FileName, null);
Settings.Default.Save();
Settings.Default.Reload();
Then I saw Settings.Default.PropertyValues has the latest updated values and tested that in debug mode,
string properyValue =
Convert.ToString(Settings.Default.PropertyValues[propertyName].PropertyValue);
strangely they don't seem to be working when I created the installer and exe . Still to figure what exactly wrong.
Can someone point me out if I am complicating things and missing something?
Update 1
After nflash's comment , I checked when the file was created. The file was not created when the application starts for all 3 , I even called Settings.Default.Save right at the start but it doesn't create the file Settings.Default.<PropertyName> , Settings.Default.Properties are instantiated but Settings.Default.PropertyValues not.
Only once I make a change in the Settings and Save , the file is created.
Update2
Right now the solution that I came with is
source.GetType().GetProperty(setting.Name, typeof(string))
.SetValue(source, "NewValue", null);
As mentioned by nflash , it would be type safe (Although Reflection has it's demirits) . But the Settings.Default.<PropertyName> is synchronized and instantiated correctly hence.
Just want to add that you can only change settings with "User" scope. When you save the new value of the setting the value is not saved in the config in the application path but instead it is saved in the user.config inside the %localappdata% folder (%localappdata%\CompanyName\ApplicationName_someGUID\AppVersion)
Update:
About your last update, the user.config file is only created when you save a setting with a value different from the default value of the setting.
I'm not sure if you still have questions about this, so I'm trying to add more info:
Settings.Default.<PropertyName> as wonko79 pointed out is just a property accessor to the corresponding value. If you look at the code behind the settings (or just Go To Definition of the property) you will see something like this:
public string PropertyName {
get {
return ((string)(this["PropertyName"]));
}
set {
this["PropertyName"] = value;
}
}
The array operator is accessing the underlying structure that holds the values that in fact is the PropertyValues.
The difference between the Properties and PropertyValues is a little bit trickier. These are really two different structures (one is a SettingsPropertyCollection and the other is a SettingsPropertyValueCollection). The Properties property is defined in the ApplicationSettingsBase class and the PropertyValues is defined in the SettingsBase class.
The SettingsProperty class (elements of the SettingsPropertyCollection) contains information about the setting itself (metadata?) and its default value.
The SettingsPropertyValue class (elements of the SettingsPropertyValueCollection) contains the actual value of the setting and some additional control information, like if the value is dirty, if it is using default value, etc.
In the end of the day this is all how .NET internally manages the Settings and all that we need to know is how to get and set these settings.
I always like to work with the properties that the setting designer generates as it is strongly typed and already makes the cast to the corresponding type. Also using the Properties or PropertyValues requires a string as a parameter and in case of a typo I will only get an error in runtime as opposed to the compile error that I get if misspell the name of the property.
To save the settings after changing them you have to call
Settings.Default.Save();
Settings.Default.<PropertyName> is a property accessor to the corresponding settings value.
Settings.Default.Properties is a collection of all settings in your settings file.
Settings.Default.PropertyValues is a collection of all values of the settings in your settings file.
Maybe Using Settings in C# is a good starting point to read.
The article mentioned by user1064248 is good info, but does not address the PropertyValues issue. I cannot add anything to the good advice from Rameez and nflash except for this pragmatic advice: If you wish to force PropertyValues to populate, you need only to force a value to change. In my settings I have a DateTime property called "Timestamp" and if you put this in the form Load event, you will find that nn1 is zero, and nn2 contains the count all of the properties:
int nn1 = Properties.Settings.Default.PropertyValues.Count;
Properties.Settings.Default.Timestamp = DateTime.UtcNow; // Forces PropertyValues to load
int nn2 = Properties.Settings.Default.PropertyValues.Count;

When to use Properties.Settings.Default in C#

What are the best practices for using the Properties.Settings.Default config settings in C#? I see it commonly, but I often don't know when to utilize it vs. when I should just hard code values. Thanks!
Basically, I try to avoid hardcoding values in code, mainly because if there's ever a need to change their value it requires a re-compile of the app.
It's usually beneficial to have some sort of common object that exposes all your settings via public properties so that you are referencing the settings the same way throughout the app.
Example:
public static SomeReferenceClass
{
public static string TimeOfDay { get{ return Properties.Settings.Default.TimeOfDay; }}
}
Then Later on to call it
SomeReferenceClass.TimeOfDay;
My rule of thumb has always been that if the values of the properties need to change without modifying the code then make them an external/configurable property. If you will never need to change their value, then they're a constant and can be hard-coded.
Basically, if these values need to be configured/changed put them in Properties.Settings.Default. You can hard code constants.
personally, I use the default setting when the user or application setting are not specified or persisted.
I'd never hardcode a setting that might change based on any number of variables such as environment, user, application, or whatever.
I generally create settings providers that implement an interface. That way, you can easily change out how to gather your configuration settings without changing the business logic.

Save/Read object values using Properties.Settings

I want to save the state of my object when the software exit and restore it when the software loads. Im doing this (code below) now, but I think there must be another bether/smarter way to do that. :)
Ive read a little about Databing, but for this I would need to modify MyClass, deriving it from CollectionBase, etc.. Do you think it is a good ideia?
One more thing, is there a way to store a Point*F* (PointFFFF no Point) directly in Properties.Settings (I could not find it in browse)?
LoadConfig()
{
MyClass.ItemA = Properties.Settings.Default.ItemA;
}
SaveConfig()
{
Properties.Settings.Default.ItemA = MyClass.ItemA;
Settings.Default.Save();
}
I see nothing wrong with it. Yes, you could certainly use bindings also. You can create settings for other non-primitive types by going to type "Browse..." and then select the type you want to save. You would be able to browse for System.Drawing.Point and use that. It'll serialize the value in the app.config file.

config and settings component for C#

I'm starting to design a config and settings component for an application.
I need an easy way to read dictionary style settings and also a way to store simple arrays into a persistence level.
is there a commonly used component already available ? (something like log4net for logging)
what options should I look into ?
You don't really need to do that: .NET BCL already has everything you need.
Take a look at App.Config and the ConfigurationManager class.
If you expand the Properties folder in the SolutionExplorer you should find a Settings.Settings item. Double clicking on this will open the settings editor. This enables you to declare and provide initial values for settings that can either be scoped to the application or the current user. Since the values are persisted in Isolated storage you do not need to worry about what privileges the user is executing under.
For a wee example:
I created a new string setting with the name Drink and a TextBox named drinkTextBox. The code to assign the current value to the text box is:
drinkTextBox.Text = Properties.Settings.Default.Drink;
and to update the value persisted:
Properties.Settings.Default.Drink = drinkTextBox.Text;
Properties.Settings.Default.Save();
Depending on how flexible you want it to be, you can use the build in Settings designer (go to Project Properties > Settings) and you can add settings there.
These are strongly typed and accessible through code.
It has built in features like Save, Load and Reload
We'll often create a sealed class that has a number of properties that wrap calls to the the System.Configuration.ConfigurationManager class. This allows us to use the standard configuration managagement capabilities offered by the class and the app/web.config file but make the data very easy to access by other classes.
For example we might create a property to expose the connection string to a database as
public static string NorthwindConnectionString
{
get{return ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString
}
While it creates a wrapper around one line of code, which we usually try to avoid, it does make certain confiuration properties accessible via intellisense and provides some insullation around changes to the location of underlying configuration data. If we wanted to move the connection string to the registry, we could do so without major impact to the application.
We find this most helpful when we have larger teams or when we need to hand off code from one team to another. It keeps people from needing to remember what the various settings were named in the config files and even where configuration information is stored (config file, database, registry, ini file, etc.)
Building a dictionary in the standard settings
Using the standard Settings, it isn't possible to store dictionary style settings.
To emulate the System.Collections.Specialized.StringDictionary,
what I've done in the past is used two of the System.Collections.Specialized.StringCollection typed settings (this is one of your options for the setting type).
I created one called Keys, and another called values. In a class that needs these settings I've created a static constructor and looped through the two StringCollections and built the StringDictionary into a public static property. The dictionary is then available when needed.
public static StringDictionary NamedValues = new StringDictionary();
public static ClassName() // static construtor
{
StringCollection keys = Properties.Settings.Default.Keys;
StringCollection vals = Properties.Settings.Default.Values;
for(int i = 0; i < keys.Count(); i++)
{
NamedValues.Add(keys[i], vals[i]);
}
}
For noddy apps I use appSettings. For enterprise apps I usually create some custom config sections. CodeProject has some excellent articles on this.
For your scenario of key/value pairs I'd probably use something like this.

Winforms - Dynamic Load / Save Settings

I have a "settings file" in my Winforms application called Settings.settings with a partial class for custom methods, etc. Is there a way to load / save dynamic settings based on arbitrary keys?
For example, I have some ListViews in my application in which I want to save / load the column widths; Instead of creating a width setting for each column for each list view I would like a simple method to load / save the widths automatically.
Below is an example of the save method I have tried:
internal sealed partial class Settings
{
public void SetListViewColumnWidths(ListView listView)
{
String baseKey = listView.Name;
foreach (ColumnHeader h in listView.Columns)
{
String key = String.Format("{0}-{1}", baseKey, h.Index);
this[key] = h.Width;
}
}
}
When running that code I get the error "The settings property 'TestsListView-0' was not found." Is there something I am missing?
Store your column width settings in an Xml Serializable object. Ie, something that implements IXmlSerializable then create a single setting entry of that type in Settings.settings.
A good option would probably be an Xml Serializable Dictionary. A quick google search found quite a few different blog posts that describe how to implement that.
As mentioned in other answers you'll need to ensure that this object is a User setting. You may also need to initialize the setting instance. Ie, create a XmlSerializableDictionary() instance and assign it to the setting if the setting is null. The settings subsystem doesn't create default instances of complex setting objects.
Also, if you want these settings to persist between assembly versions (ie, be upgradable) you will need to upgrade the settings on application startup. This is described in detail on Miha Markič's blog and Raghavendra Prabhu's blog.
I think the error
The settings property
'key' was not found.
occurs because the 'key' value does not exist in your settings file (fairly self-explanatory).
As far as I am aware, you can't add settings values programmatically, you might need to investigate adding all of the settings you need to the file after all, although once they are there, I think you'll be able to use the sort of code you've given to save changes.
To Save changes, you'll need to make sure they are 'User' settings, not 'Application'.
The Settings file is quite simple XML, so you might be able to attack the problem by writing the XML directly to the file, but I've never done it, so can't be sure it would work, or necessarily recommend that approach.
http://msdn.microsoft.com/en-us/library/cftf714c.aspx is the MSDN link to start with.
You can do Settings.Save() or similar on user settings, but note that such settings would NOT get persisted to the xxx.exe.config file in your app directory as you'd expect. They actually go somewhere deep inside the user folder (search your drive for xxx.exe.config to find it). Next time that you manually change xxx.exe.config in your app directory, the change will mysteriously not apply (the system is still using the saved one from the user directory).

Categories

Resources