I have a number of application settings (in user scope) for my custom grid control. Most of them are color settings. I have a form where the user can customize these colors and I want to add a button for reverting to default color settings. How can I read the default settings?
For example:
I have a user setting named CellBackgroundColor in Properties.Settings.
At design time I set the value of CellBackgroundColor to Color.White using the IDE.
User sets CellBackgroundColor to Color.Black in my program.
I save the settings with Properties.Settings.Default.Save().
User clicks on the Restore Default Colors button.
Now, Properties.Settings.Default.CellBackgroundColor returns Color.Black. How do I go back to Color.White?
#ozgur,
Settings.Default.Properties["property"].DefaultValue // initial value from config file
Example:
string foo = Settings.Default.Foo; // Foo = "Foo" by default
Settings.Default.Foo = "Boo";
Settings.Default.Save();
string modifiedValue = Settings.Default.Foo; // modifiedValue = "Boo"
string originalValue = Settings.Default.Properties["Foo"].DefaultValue as string; // originalValue = "Foo"
Reading "Windows 2.0 Forms Programming", I stumbled upon these 2 useful methods that may be of help in this context:
ApplicationSettingsBase.Reload
ApplicationSettingsBase.Reset
From MSDN:
Reload contrasts with Reset in that
the former will load the last set of
saved application settings values,
whereas the latter will load the saved
default values.
So the usage would be:
Properties.Settings.Default.Reset()
Properties.Settings.Default.Reload()
Im not really sure this is necessary, there must be a neater way, otherwise hope someone finds this useful;
public static class SettingsPropertyCollectionExtensions
{
public static T GetDefault<T>(this SettingsPropertyCollection me, string property)
{
string val_string = (string)Settings.Default.Properties[property].DefaultValue;
return (T)Convert.ChangeType(val_string, typeof(T));
}
}
usage;
var setting = Settings.Default.Properties.GetDefault<double>("MySetting");
Properties.Settings.Default.Reset() will reset all settings to their original value.
I've got round this problem by having 2 sets of settings. I use the one that Visual Studio adds by default for the current settings, i.e. Properties.Settings.Default. But I also add another settings file to my project "Project -> Add New Item -> General -> Settings File" and store the actual default values in there, i.e. Properties.DefaultSettings.Default.
I then make sure that I never write to the Properties.DefaultSettings.Default settings, just read from it. Changing everything back to the default values is then just a case of setting the current values back to the default values.
How do I go back to Color.White?
Two ways you can do:
Save a copy of the settings before the user changes it.
Cache the user modified settings and save it to Properties.Settings before the application closes.
I found that calling ApplicationSettingsBase.Reset would have the effect of resetting the settings to their default values, but also saving them at the same time.
The behaviour I wanted was to reset them to default values but not to save them (so that if the user did not like the defaults, until they were saved they could revert them back).
I wrote an extension method that was suitable for my purposes:
using System;
using System.Configuration;
namespace YourApplication.Extensions
{
public static class ExtensionsApplicationSettingsBase
{
public static void LoadDefaults(this ApplicationSettingsBase that)
{
foreach (SettingsProperty settingsProperty in that.Properties)
{
that[settingsProperty.Name] =
Convert.ChangeType(settingsProperty.DefaultValue,
settingsProperty.PropertyType);
}
}
}
}
Related
My speech recognition project include 2 forms form1 & form2. Form2 is my main form but before loading form2 my program take a variable value from user through form1 and pass it to form2. It means at start my program opens form1 takes value & pass it to form2 then form2 is shown.
Now my question is how to
make form1 load only at programs 1st launch after installation and after 1st launch directly form2 is loaded thereafter?
means form1 should not be loaded after that..
I suggest to use a simple textfile where you could store the input value recorded the first time your app starts, then, check if the file with the value exists and read it back.
For Example
string customValue = string.Empty;
string appData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
appData = Path.Combine(appData, "MyAppName");
if(!Directory.Exists(appData))
Directory.CreateDirectory(appData);
string appDataFile = Path.Combine(appData, "MyAppNameSettings.txt");
if(File.Exists(appDataFile))
customValue = File.ReadAllText(appDataFile);
else
{
customValue = AskUserForTheFirstTimeValue();
File.WriteAllText(appDataFile, customValue);
}
The file is stored in a subfolder of the common application data (C:\programdata) created to store your data files. You check if the file exists at first launch. If the file exists you read its content (assumed to be a simple string here), if the file doesn't exist then you ask the input and store the value for the successive runs of your app.
You can create a Registry Key in Windows Registry (regedit), and when you start your program verify if its exists and the value.
Link about Registry Keys:
http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey(v=vs.110).aspx
You should have a settings file that keeps a variable like IsFirstRun = true; This application should be distributed and compiled with this file, at start up you should read this file and if you encounter the true state you should load the appropriate forms. You should also ensure that the value is immediately set to false for the second launch condition.
have a look at .net's setting class.
There are two ways I can suggest:
First one
Use the application configuration file:
Creating such file in c# is pretty easy, per usual if you start with a standard Windows Forms Project Template you will most likely already have an app.config in that project, if not, follow instructions from here (under Application Configuration Files).
Add a simple boolean value to the file like so (that appSettings-node is created under the root configuration-node:
<appSettings>
<add key="FirstRun" value="true" />
</appSettings>
In your first form, where you do your application configuration you add code to manipulate your app.config programmatically using the ConfigurationManager-Class for the event that configuration has been finished and can be saved (probably some button click, note that you will need a Reference to System.Configuration):
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
bool myVal = bool.Parse(config.AppSettings.Settings["FirstRun"].Value);
if (myVal)
{
// MessageBox.Show("yep, its true");
config.AppSettings.Settings["FirstRun"].Value = false.ToString();
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
else
{
// MessageBox.Show("na, its not true anymore.");
}
Second one
Use a property grid for your application configuration:
Since from your description it seems you only use the first form to enter some application configuration values, I would recommend using the PropertyGrid-Control for that.
That control can be easily bound to an object that exposes some properties (what a surprise) that are then used to render a standardized control containing captions and value selection controls dependend on the property's types, for example:
public class Settings
{
public int MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
}
Then you check at your program start, whether the configuration file (you define the path) exists, and if so, try to deserialize an object from its xml (sample below works for primitive types, for more complex ones you might have to extend the serializer, but you get the idea).
That serialized object represents your saved application settings, so you do not need to open up the propertygrid-form anymore.
If no file could be found the grid gets initialized with a simple new constructed object and you show that form:
this goes into your initialization code:
FileInfo file = new FileInfo("SaveHere.xml");
if (file.Exists)
{
using(StreamReader reader = new StreamReader("SaveHere.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
Settings mySettings = (Settings)serializer.Deserialize(reader);
reader.Close();
}
}
else
{
this.propertyGrid1.SelectedObject = new Settings();
// show form code
}
this code goes into the event code where you want to save your configuration
using(StreamWriter writer = new StreamWriter("SaveHere.xml",false))
{
XmlSerializer serializer = new XmlSerializer(this.propertyGrid1.SelectedObject.GetType());
serializer.Serialize(writer, this.propertyGrid1.SelectedObject);
writer.Close();
}
I am building an application, which has a form where the user can configure all his settings. When the application is loaded, the previously configured settings should reflect to the GUI (The UI should be consistent to the saved settings).
What I am currently doing is creating the settings on the project properties and I have a LoadSettings() method, which gets the values and outputs them to each component on the UI.
The thing is that this is getting VERY messy, and I don't like it at all.
So, that got me wondering, what are the correct approaches to achieve what I want, but yet getting high quality code? Any patterns for that?
private void LoadConfigs()
{
checkBoxStartOnStartup.Checked = ExistKeyValue(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Wallbase Downloader");
checkBoxCheckWallbaseOnline.Checked = Settings.Default.CheckWallbaseOnlineStartup;
comboBoxResolution.SelectedIndex = comboBoxResolution.FindStringExact(Settings.Default.Resolution == string.Empty
? GetScreenResolution()
: Settings.Default.Resolution);
comboBoxCondition.SelectedIndex = Settings.Default.ConditionIndex;
textBoxWallpaperFolders.Text = Settings.Default.WallpaperFolder;
numericChangeInterval.Text = Convert.ToString(Settings.Default.ChangeIntervalValue);
comboBoxChangeInterval.SelectedIndex = Settings.Default.ChangeIntervalIndex;
numericCheckInterval.Text = Convert.ToString(Settings.Default.CheckIntervalValue);
comboBoxCheckInterval.SelectedIndex = Settings.Default.CheckIntervalIndex;
numericWallpapersToLookFor.Text = Settings.Default.WallpapersToLookFor.ToString();
}
Well, WinForms are not the cleanest framework around...
What you could do is to load all settings when your application starts up and store them in some storage that is available to all forms, e.g. in a static property in a helper settings class.
You can then access that static property from each form when it loads and make all necessary changes to the form based on the settings.
You can use a Hashtable and use English strings for key to make your code really readable. Then serialize it to file on exit and deserialize it back when application loads. Save the serialized file to some common location so that you do not lose it.
I decided to use Properties.Settings to store some application settings for my ASP.net project. However, when trying to modify the data, I get an error The property 'Properties.Settings.Test' has no setter, since this is generated I have no idea what I should do to change this as all my previous C# Projects have not had this issues.
My guess is that you defined the property with the Application scope, rather than the User scope. Application-level properties are read-only, and can only be edited in the web.config file.
I would not use the Settings class in an ASP.NET project at all. When you write to the web.config file, ASP.NET/IIS recycles the AppDomain. If you write settings regularly, you should use some other settings store (e.g. your own XML file).
As Eli Arbel already said you can’t modify values written in web.config from your application code. You can only do this manually but then the application will restart and this is something you don’t want.
Here is a simple class you can use to store values and make them easy to read and modify. Just update the code to suite your needs if you’re reading from XML or database and depending on whether you want to permanently store modified values.
public class Config
{
public int SomeSetting
{
get
{
if (HttpContext.Current.Application["SomeSetting"] == null)
{
//this is where you set the default value
HttpContext.Current.Application["SomeSetting"] = 4;
}
return Convert.ToInt32(HttpContext.Current.Application["SomeSetting"]);
}
set
{
//If needed add code that stores this value permanently in XML file or database or some other place
HttpContext.Current.Application["SomeSetting"] = value;
}
}
public DateTime SomeOtherSetting
{
get
{
if (HttpContext.Current.Application["SomeOtherSetting"] == null)
{
//this is where you set the default value
HttpContext.Current.Application["SomeOtherSetting"] = DateTime.Now;
}
return Convert.ToDateTime(HttpContext.Current.Application["SomeOtherSetting"]);
}
set
{
//If needed add code that stores this value permanently in XML file or database or some other place
HttpContext.Current.Application["SomeOtherSetting"] = value;
}
}
}
Here:
http://msdn.microsoft.com/en-us/library/bb397755.aspx
is the solution for your problem.
I'm a beginner in winforms, and just starting using it's preferences.
So, I add in my Settings.settings a Value named path, as string and User Scope.
I change it when I choose a new path with a FolderBrowserDialog and then, after a click on a Ok button, i change the preferences like this :
private void buttonPref_Click(object sender, EventArgs e)
{
Form2 subForm2 = new Form2(textBoxRep.Text);
subForm2.ShowDialog();
if (subForm2.DialogResult == DialogResult.OK)
{
Settings.Default.path= subForm2.rep();
subForm2.Close();
}
else
{
subForm2.Close();
}
}
public string rep()
{
return textBoxRep.Text;
}
Then, when I run my Application, I load the value in my preferences :
textBoxRep.Text = Settings.Default.path;
But, the value is set to empty after every new run.
So I tried with a Application Scope, but I got a read Only error on this : Settings.Default.path
How can I fix this? Is there a way to register the settings after mofified them?
Thank you.
you need to call Save method as below
Settings.Default.path= subForm2.rep();
Settings.Default.Save();
Settings that are application-scoped are read-only, and can only be
changed at design time or by altering the .config file in between
application sessions. Settings that are user-scoped, however, can be
written at run time just as you would change any property value. The
new value persists for the duration of the application session. You
can persist the changes to the settings between application sessions
by calling the Save method.
How To: Write User Settings at Run Time with C#
You need to also call Settings.Default.Save();
I store the directory path of a folder in Properties.Settings.Default.Temporary and I allow the user to change this value and other settings using a PropertyGrid.
When the user decides to reset the Settings, I would like to change Properties.Settings.Default.Temporary to the value of System.IO.Path.GetTempPath() by using Properties.Settings.Default.Reset()
I know about System.Configuration.DefaultSettingValueAttribute. Something like this:
[global::System.Configuration.DefaultSettingValueAttribute(System.IO.Path.GetTempPath())]
does not work.
I also read Storing default value in Application settings (C#), which described a related problem, but I wonder if there is a way to solve my problem in the way described above.
The DefaultSettingValueAttribute.Value property is a string, therefore you cannot pass a function call to be called when the value is used. In fact there is no ability to pass code to an attribute: only literals are possible.
Instead in your applications code where you reset the settings, follow this by setting and settings that you want to have values that are not literals at compile time (eg. dependent on the execution environment).
I just had an idea for a workaround myself:
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute(null)]
public string TemporaryDirectory
{
get
{
if (this["TemporaryDirectory"] == null)
{
return System.IO.Path.GetTempPath();
}
return ((string)this["TemporaryDirectory"]);
}
set
{
if (System.IO.Directory.Exists(value) == false)
{
throw new System.IO.DirectoryNotFoundException("Directory does not exist.");
}
this["TemporaryDirectory"] = value;
}
}
I don't know, if this has any side effects, but so far it seems to work. I am sorry that I had this idea shortly after posting. I should've thought about the problem a bit longer.