WinForm Settings are not saved - c#

I use the VSTO built-in settings file in order to save Windows- application settings.
I have a checkBox on my WinForm, whereas at form load I read its state (checked or unchecked)
from the appropriate property in the settings file.
This works fine as long as I do not exit the application.
However, when I quit and then execute the application again- the settings are not saved from last execution and the checkBox state is not as the last preference.
I use "user" scope to save the settings.
On form load, extract the checkBox state from Settings.
private void MyFormLoad(object sender, EventArgs e)
{
//Find the appropriate property in the Settings file
System.Configuration.SettingsProperty property;
property = P_Settings.Settings.Default.Properties[checkBox.Name];
if (property != null)
checkBox.Checked = Convert.ToBoolean(property.DefaultValue);
}
On form close, Synchronize settings file with form status.
private void ButtonApplyClick(object sender, EventArgs e)
{
System.Configuration.SettingsProperty property;
property = P_Settings.Settings.Default.Properties[checkBox.Name];
property.DefaultValue = checkBox.Checked.ToString();
P_Settings.Settings.Default.Save();
}

I don't think the DefaultValue is where you should store the value for a settings property. That looks more like a part of the property definition (which should stay constant across application runs and thus be hard-coded) rather than like something that will be saved along with the settings.
Instead, try directly using the indexer of the settings object:
Loading:
object propValue = P_Settings.Settings.Default[checkBox.Name];
if (propValue != null) {
checkBox.Checked = Convert.ToBoolean(propValue);
}
Saving:
P_Settings.Settings.Default[checkBox.Name] = checkBox.Checked.ToString();
P_Settings.Settings.Default.Save();
EDIT: Originally, you were storing the checkbox state in the DefaultValue property of the settings property. The DefaultValue is meant to provide a default value that will be returned if no settings value was found in the stored settings. It is not a value that will be stored with the settings, as it is not supposed to be user-defined, or changed during the application's run.
Therefore, what you tried before resulted in the observed behavior: You could assign a value to DefaultValue, which would stay for as long as the application was active, but that value was not stored upon P_Settings.Settings.Default.Save() or restored upon application startup, so upon the next launch of your application, DefaultValue would have its default value (probably null) again.

Related

Show a Messagebox if program is ran for the first time in C#

When a user runs the program for the first time I want a message box to show up.
I was thinking of something like this:
private void Form1_Load(object sender, EventArgs e)
{
if(firstTime)
{
MessageBox.Show("Welcome");
}
How could I get my program to display a message box when a user launches the program for the first time in c#?
You would need to store that information somewhere
File
System registry
Database
Settings in application
Then read the value, and setup the firstTime flag prior to check.
You can add a parameter to the application settings.
Go to the solution explorer in the section Properties and double click on Settings.settings.
Add a parameter named for example IsFirstLaunch and set type to bool with value True.
Then you can write:
if ( Properties.Settings.Default.IsFirstLaunch )
{
Properties.Settings.Default.IsFirstLaunch = false;
Properties.Settings.Default.Save();
MessageBox.Show("Welcome");
}
The settings are stored in:
c:\Users\{UserName}\AppData\Local\{Assembly CompanyName}\{Assembly Name}.Url__________
So be careful to set Assembly CompanyName in the AssemblyInfo.cs in the same section.
Assembly Name is from the application project properties (double click on this Properties section).
You can delete this file to test again.

What is the best way to store some data in VSTO addin?

I have developed one outlook add-in, that has to be On or Off.
to do that i have declared one static variable as shown below,
ThisAddIn.cs
public static bool isAddInOn = false;
RibbonButton.cs
private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
{
if (ThisAddIn.isAddInOn )
{
ThisAddIn.isAddInOn = false;
btnRibbon.Label = "Disabled";
}
else
{
ThisAddIn.isAddInOn = true;
btnRibbon.Label = "Enabled";
}
}
It is working. But the static variable reset again when i close outlook and open it again. That means when i open outlook by default my add-in is in disabled state.
I just want to store that value at some place. so i can check that value when outlook reopened.
Scenario:
1) open outlook
2) Enable add-in by clicking on its logo (that is in ribbon)
3) now close the outlook
4) when i open outlook again it must enabled
so how can i achieve this ?
There are several techniques you can use to achieve this result. For sure your settings must be serialized to some storage/deserialized during startup of add-in.
One of possible solution could be to use registry for that (in this case probably HKCU (Current user, then it will be private for each user using your add-in) and no special permission is needed.
For storing variable:
public void StoreInRegistry(string keyName, string value)
{
RegistryKey rootKey = Registry.CurrentUser;
string registryPath = #"Software\YourCompanyName\YourAddInName";
using (RegistryKey rk = rootKey.CreateSubKey(registryPath))
{
rk.SetValue(keyName, value, RegistryValueKind.String);
}
}
For reading variable:
public string ReadFromRegistry(string keyName, string defaultValue)
{
RegistryKey rootKey = Registry.CurrentUser;
string registryPath = #"Software\YourCompanyName\YourAddInName";
using (RegistryKey rk = rootKey.OpenSubKey(registryPath, false))
{
if (rk == null)
{
return defaultValue;
}
var res = rk.GetValue(keyName, defaultValue);
if (res == null)
{
return defaultValue;
}
return res.ToString();
}
}
Such stored/retrieved variable should be used during add-in initialization to set your properties. So modification could look like:
ThisAddin.cs
public static bool isAddInOn = ReadFromRegistry("MySetting1", "0") == "1";
RibbonButton.cs
private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
{
if (ThisAddIn.isAddInOn )
{
ThisAddIn.isAddInOn = false;
btnRibbon.Label = "Disabled";
}
else
{
ThisAddIn.isAddInOn = true;
btnRibbon.Label = "Enabled";
}
StoreInRegistry("MySetting1", ThisAddIn.isAddInOn ? "1" : "0");
}
Other options could serialization to file - some class with settings serialized to i.e. isolated storage, database (local or central) etc.
I've used several methods over the years to store configuration data for users.
Properties.Settings.Default.Properties, so writing in the application project properties. It's solid, never had an issue with it, for hundreds of users over several years.
Local config files in text, so writing to a known area for the user with fallback. In a stable environment, one can choose the home area for the user, and read/write to the local config file, which also makes it accessible to support if it breaks and needs manual changes. As a fallback, one could write to the local temp folder.
Registry is an option i have not used in this case, but it is likely to be a good choice.
Performance is likely a key concern considering it will impact the UI for users. Another concern is ease of use for the developer. For both, my choice would be setting it in the application's properties, where reading and writing is very simple and handled within code, and likely very fast.
Write
Properties.Settings.Default.PropertyName = propertValue;
Read
var propertValue = Properties.Settings.Default.PropertyName;
2018 UPDATED ANSWER
The recommended way to achieve this is now to use the already configured settings files in your project's properties. These files are auto-generated when create your project :
And open the following window when clicked :
You can access your settings value programmatically into Properties.Settings.Default.Properties anywhere.
The header bar at the top of the Settings page contains several controls:
Synchronize
Synchronize restores user-scoped settings that the application uses at run time or during debugging to their default values as defined at design time. To restore the data, remove run-time generated application-specific files from disk, not from project data.
Load Web Settings
Load Web Settings displays a Login dialog box that enables you to load settings for an authenticated user or for anonymous users. This button is enabled only when you've enabled client application services on the Services page and specified a Web settings service location.
View Code
For C# projects, the View Code button enables you to view the code in the Settings.cs file. This file defines the Settings class, which enables you to handle specific events on the Settings object. In languages other than Visual Basic, you must explicitly call the Save method of this wrapper class in order to persist the user settings. You usually do this in the Closing event handler of the main form. Following is an example of a call to the Save method:
C#
Properties.Settings.Default.Save();
For Visual Basic projects, the View Code button enables you to view the code in the Settings.vb file. This file defines the MySettings class, which enables you to handle specific events on the My.Settings object. For more information about accessing application settings by using the My.Settings object, see Access application settings.
For more information about accessing application settings, see Application settings for Windows Forms.
Access modifier
The Access modifier button specifies the access level of the Properties.Settings (in C#) or My.Settings (in Visual Basic) helper classes that Visual Studio generates in Settings.Designer.cs or Settings.Designer.vb.
For Visual C# projects, the access modifier can be Internal or Public.
For Visual Basic projects, the access modifier can be Friend or Public.
By default, the setting is Internal in C# and Friend in Visual Basic. When Visual Studio generates helper classes as Internal or Friend, executable (.exe) applications cannot access the resources and settings that you have added to class libraries (.dll files). If you have to share resources and settings from a class library, set the access modifier to Public.
For more information about the settings helper classes, see Manage application settings.
Settings grid
Settings Grid is used to configure application settings. This grid includes the following columns:
Name
Enter the name of the application setting in this field.
Type
Use the drop-down list to select a type for the setting. The most frequently used types appear in the drop-down list, for example, String, (Connection string), and System.Drawing.Font. You can choose another type by selecting Browse at the end of the list, and then selecting a type from the Select a Type dialog box. After you choose a type, it's added to the common types in the drop-down list (for the current solution only).
Scope
Select either Application or User.
Application-scoped settings, such as connection strings, are associated with the application. Users can't change application-scoped settings at run time.
User-scoped settings, such as system fonts, are intended to be used for user preferences. Users can change them at run time.
Value
The data or value associated with the application setting. For example, if the setting is a font, its value could be Verdana, 9.75pt, style=Bold.
Documentation link
Reading settings
Writing settings
Settings can be stored as a hidden (associated) item in a folder, such as the Inbox or the Calendar folder. For example, Outlook stores the list of categories as a hidden item in the Calendar folder. POP3 message ids are stored in a hidden item in the Inbox. The advantage of the hidden items is the roaming capability - Exchange mailbox user can see the data from any computer.
You can see the hidden items in OutlookSpy (I am its author) - click IMAPIFolder button, go to the "Associated Contents" tab.
Programmatically, such items can be accessed using MAPIFolder.GetStorage in the Outlook Object Model.

Winforms preferences values

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();

data binding non-strings to TextBox.Text (WinForms)

I'm storing a whole bunch of settings for my winforms program in various .settings files.
Included in these settings are System.Drawing.Point, System.Drawing.Location, System.TimeSpan, System.DateTime, etc...
When I bind a form's Location to a System.Drawing.Location, and call the .Save() method, it all seems to work fine. That is, since there doesn't seem to be a need for a cast, the form's System.Drawing.Location is directly compatible with the System.Drawing.Location setting stored in the .settings file.
Additionally, if I say TimeSpan timeSpan = Settings.Duration; that also works fine.
Now, I have made a large settings form, where the user can adjust various parameters, including the various DateTime and TimeSpan settings. These are visible and editable in many TextBox, which I have data bound in the following way:
Settings DefaultSettings = Settings.Default;
TextBox1.DataBindings.Add(("Text", DefaultSettings, "Duration", false, DataSourceUpdateMode.OnValidation, new TimeSpan(00, 30, 00));
The TimeSpan is visible in the TextBox, however when I try to edit it and call Save() on the settings data source, I get the following error:
Value of '0' is not valid for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'.
Parameter name: Value
The error originates from the Visual Studio generated code block:
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("00:30:00")]
public global::System.TimeSpan StartWorkDay {
get {
return ((global::System.TimeSpan)(this["Duration"]));
}
set {
this["Duration"] = value;
}
}
I think the problem is caused by the fact that it's trying to turn a string into a System.TimeSpan, and the various other classes I have in my .settings file.
Since I'm binding them using the DataBindings.Add( which accepts strings for the parameters, I can't cast or use the new keyword there.
I could handle it all manually in code: updating the settings file by constructing the objects parameter-by-parameter, but I have so many settings stored in so many TextBoxes and NumericUpDowns that I would prefer to just bind them straight to the TextBox, assuming that's possible.
What is the easiest way I can achieve this?
You could declare a “conversion property” (I just invented that term) in the Settings class:
public class Settings
{
// The real property
public TimeSpan StartWorkDay { get; set; }
// The conversion property
public string StartWorkDayString
{
get
{
return StartWorkDay.ToString();
// (or use .ToString("...") to format it)
}
set
{
StartWorkDay = TimeSpan.Parse(value);
// (or use TryParse() to avoid throwing exceptions)
}
}
}
... and then bind the textbox to that.
I tried the following code in a sample windows form application and it did the save without any exceptions.
// Define the settings binding source
private System.Windows.Forms.BindingSource settingsBindingSource;
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.durationTextBox = new System.Windows.Forms.TextBox();
this.settingsBindingSource = new BindingSource(this.components);
this.settingsBindingSource.DataSource = typeof(WindowsFormsApplication1.Properties.Settings);
this.durationTextBox.DataBindings.Add(new Binding("Text", this.settingsBindingSource, "Duration", true));
}
// In the form load event where the textbox is displayed
private void Form1_Load(object sender, System.EventArgs e)
{
settingsBindingSource.DataSource = Settings.Default;
}
// save button click
private void button1_Click_1(object sender, System.EventArgs e)
{
// This saved the settings, without any exceptions
Settings.Default.Save();
}
Hope it helps.
I came up with a somewhat-elegant solution which you might be interested in:
Since the problem seemed to be that I was unable to cast or construct the data types I had in the .settings file from simple text boxes as I was using data binding, I instead made some custom controls.
For example, the TimeSpans now use a TimeSpanPicker which I made out of a DateTimePicker control, with the date disabled, the up/down toggles on, and the Value property is converted to a TimeSpan from within the picker control.
The added advantage of this method is that I don't need to do a lot of the validation I needed to before with text boxes, as the TimeSpanPicker base control DateTimePicker will only show valid times. What little validation I do need to do can be done in the Set{} property, so I don't need to define event handlers.
This seems to be working well!
Now all I need to do is replace all the text boxes with custom controls.

Reading default application settings in C#

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);
}
}
}
}

Categories

Resources