Search code examples
c#openfiledialogapplication-settingssavefiledialog

How to save Application Settings to a different location and file name


C# Windows Forms.

I have successfully used Application Settings to save and load user settings for the values of controls on my form. I have a checkbox and code where I can set whether this happens automatically (at application start and close), or not. I also have a menu so I can load them and save them during runtime. This is all using the default user.config.

Example. In Application settings I have (for one of the items, which is a radio button called RbBitRate6Mbps):

Name: BitRate6Mbps

Type: String

Scope: User

Value: False

To save the settings I have a menu item, Save Defaults. This runs:

if (RbBitRate6Mbps.Checked == true)
{
    Settings.Default["BitRate6Mbps"] = "True";
}

else
{
    Settings.Default["BitRate6Mbps"] = "False";
}

Settings.Default.Save();

To load the settings back in I have a menu item, Load Defaults. This runs:

if (Settings.Default["BitRate6Mbps"].ToString() == "True")
{
    RbBitRate6Mbps.Checked = true;
}

else
{
    RbBitRate6Mbps.Checked = false;
}

There are about 10 other controls I save and load (text boxes, check boxes and radio buttons), in the rest of the above code. This is all working with no issues.

Now I would like to have several sets of these settings, each will contain some identical values and some different ones. Each will have a different file name and be saved into a custom location (which will be the app folder, by default). I do not mind what format the file is (xml, ini, etc), but if it is the same as the default, this would be good.

I have created new menu items, Save Custom Settings and Load Custom Settings.

I have added a SaveFileDialog and a LoadFileDialog to hopefully be used for the above. But if these are not necessay, that is good too.

This is where I have become stuck.

I have been searching for days for a clear example of how to do this. I have been unable to find much. What I have found, I have been unable to understand the documentation.

I am thinking loading the settings back in will be the easier part? But I also think, for saving the file, using:

Settings.Default.Save();

Will not accomplish my aims as it will just write to the default user.config file ?

Is what I want to do possible?

If so does anyone have any instructions and example code?


Solution

  • Update. I have installed a new Settings Provider and it is working well. It saves the XML to the app folder. I have also set up INI files to save the settings. Using both a custom path and custom file name. It allows for multiple INI files to be created. This also works extremely well.

    Edit: Updated code (and instructions) so it is no longer necessary to create any custom folder manually. If it does not exist, it will be created.

    The XML Settings Provider developers project is located here:

    Settings Providers on Github

    The INI file developers project (and demo) is located here:

    C# WinForms Ini File demo on Github

    Below are the instructions for setting up the new Settings Provider with an XML file and following that are the instructions for saving the settings to INI files (both types can be used in the same project at the same time, as I am doing here):

    Using a new Settings Provider to save settings in an XML file:

    1. Setup the Application Settings (in Solution Explorer, right-click on the App. Then Select: Properties. Then open: Settings).

    Name: txtFullName
    Type: String
    Scope: User
    Value: John Doe
    
    Name: txtSchool
    Type: String
    Scope: User
    Value: Oxford
    
    Name: txtClass
    Type: String
    Scope: User
    Value: 4B
    
    Name: chkActiveStudent
    Type: bool
    Scope: User
    Value: True
    

    2. Install, from NuGet the new Settings Provider (in Solution Explorer, right-click on: References. Then Select: Manage NuGet Packages. Then search for: PortableSettingsProvider. Install it).

    3. In Program.cs modify static void Main(). Add to it the lines below.

    //PortableSettingsProvider.SettingsFileName = "portable.config";
    //PortableSettingsProvider.SettingsDirectory = "c:\\\testconfig\\\school";
    //System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
    PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
    

    If accepting the default settings (the config file, portable.config, will be created in the applications folder), a properly edited static void Main() entry would look like the below.

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);        
        //PortableSettingsProvider.SettingsFileName = "portable.config";
        //PortableSettingsProvider.SettingsDirectory = "c:\\testconfig\\school";
        //System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
        PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);            
        Application.Run(new MyTestApp());
    }
    

    3a. To choose a different filename and location, remove the comments (//) and change to your preference for filename and location (double slashes are needed between the folder names). In this example I use settings.config as the filename and c:\testconfig\school as the path). In this case a properly edited static void Main() entry would look like the below.

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);        
        PortableSettingsProvider.SettingsFileName = "settings.config";
        PortableSettingsProvider.SettingsDirectory = "c:\\testconfig\\school";
        System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
        PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);            
        Application.Run(new MyTestApp());
    }
    

    3b. If you would like the settings directory to be created in a subfolder of the applications working directory, then change the code to include the subfolder name (in this example I use settings.config as the filename and Settings as the subfolder). In this case a properly edited static void Main() entry would look like the below.

    static void Main()
    {
        Application.EnableVisualStyles();        
        PortableSettingsProvider.SettingsFileName = "settings.config";
        var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
        System.IO.Directory.CreateDirectory(strSettingsDirectory);
        PortableSettingsProvider.SettingsDirectory = strSettingsDirectory;
        PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
        Application.Run(new MyTestApp());
    }
    

    4. Still in Program.cs, add the following line to the bottom of the existing using section.

    using Bluegrams.Application;
    

    5. On the form create some controls (these will correspond to the Application Settings made in step 1).

    TextBox. Name: txtFullName
    
    TextBox. Name: txtSchool
    
    Textbox. Name: txtClass
    
    Checkbox. Name: chkActiveStudent
    
    Button. Name: btnLoadSettings  Text: Load Config
    
    Button. Name: btnSaveSettings  Text: Save Config
    

    6. Enter the code for the Load Config buttons click events (btnLoadSettings).

    private void btnLoadSettings_Click(object sender, EventArgs e)
    {
        txtName.Text = Properties.Settings.Default.txtName.ToString();
        txtSchool.Text = Properties.Settings.Default.txtSchool.ToString();
        txtClass.Text = Properties.Settings.Default.txtClass.ToString();
    
        if (Properties.Settings.Default.chkActiveStudent == true)
        {
            chkActiveStudent.Checked = true;
        }
        else
        {
            chkActiveStudent.Checked = false;
        }
    }
    

    7. Enter the code for the Save Config buttons click events (btnSaveSettings).

    private void btnSaveSettings_Click(object sender, EventArgs e)
    {
        Properties.Settings.Default.txtName = txtName.Text;
        Properties.Settings.Default.txtSchool = txtSchool.Text;
        Properties.Settings.Default.txtClass = txtClass.Text;
    
        if (chkActiveStudent.Checked == true)
        {
            Properties.Settings.Default.chkActiveStudent = true;
        }
    
        else
        {
            Properties.Settings.Default.chkActiveStudent = false;
        }
    
        Properties.Settings.Default.Save();
    }
    

    8. That’s it.

    Run the app. Load the settings using the first button). Make some changes to the text on the controls. Save them using the second button.

    If you have not created a custom filename and/or path then in your app folder there should be a new file: portable.config.

    Mine is located at: C:\Users\flakie\source\repos\TestApp\TestApp\bin\Debug

    You can open the file in an txt/xml editor to verify the values were set.

    If you run the app again, and load settings, you should see the new values.

    The Code for Saving Settings to Multiple INI Files

    The following instructions are easier to implement. They do not require you to set-up the Application Settings as they are not used. The settings will be saved in 1 or more INI files.

    The path can be changed on-the-fly (though a default is set), as can the file name for the INI file.

    Again it will be using the applications own folder as the default destination (for the INI files).

    You will need to modify the Form.cs file only.

    The demo (from the link above) is easy to understand and was enough to provide me with the knowledge to create this example (and I am a C# novice).

    9. Install, from NuGet, the INI files package (in Solution Explorer, right-click on: References. Then Select: Manage NuGet Packages. Then search for: PeanutButter.INI. Install it).

    10. In your Form.cs file (Form1.cs if you have not changed the name), add the following line to the bottom of the existing using section.

    using PeanutButter.INIFile;

    11. In your Form.cs file, directly under the line, public partial class Form1 : Form, add the following single line of code.

    private IINIFile _loadedConfig;

    It should look like the below.

    public partial class Form1 : Form    {
    
        private IINIFile _loadedConfig;
    

    12. On the form create two more buttons.

    Button. Name: btnOpenIniFile  Text: Open INI
    
    Button. Name: btnSaveIniFile  Text: Save INI
    

    13. Enter the code for the Open INI buttons click event (btnOpenIniFile).

    private void btnOpenIniFile_Click(object sender, EventArgs e) {        
    
        using(OpenFileDialog OpenFileIni = new OpenFileDialog()) {
            var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
            System.IO.Directory.CreateDirectory(strSettingsDirectory);
            OpenFileIni.InitialDirectory = strSettingsDirectory;
            OpenFileIni.Filter = "INI File|*.ini";
            OpenFileIni.RestoreDirectory = true;
            OpenFileIni.CheckFileExists = true;
            OpenFileIni.CheckPathExists = true;
            OpenFileIni.Title = "Open an INI Settings File";
    
            if (OpenFileIni.ShowDialog() == DialogResult.OK)
            {
                _loadedConfig = new INIFile(OpenFileIni.FileName);    
                txtName.Text = _loadedConfig.HasSetting("UserSettings", "txtName") ? _loadedConfig["UserSettings"]["txtName"] : "";    
                txtSchool.Text = _loadedConfig.HasSetting("UserSettings", "txtSchool") ? _loadedConfig["UserSettings"]["txtSchool"] : "";    
                txtClass.Text = _loadedConfig.HasSetting("UserSettings", "txtClass") ? _loadedConfig["UserSettings"]["txtClass"] : "";
    
                if (_loadedConfig["UserSettings"]["chkActiveStudent"] == "Checked")
                {
                    chkActiveStudent.Checked = true;
                }
                else
                {
                    chkActiveStudent.Checked = false;
                }
            }
        }
    }
    

    14. Enter the code for the Save INI buttons click event (btnSaveIniFile).

    private void btnSaveIniFile_Click(object sender, EventArgs e)
    {
        using (SaveFileDialog SaveFileIni = new SaveFileDialog())
        {
            var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
            System.IO.Directory.CreateDirectory(strSettingsDirectory);
            SaveFileIni.InitialDirectory = strSettingsDirectory;
            SaveFileIni.Filter = "INI File|*.ini";
            SaveFileIni.Title = "Save an INI Settings File";
    
            if (SaveFileIni.ShowDialog() == DialogResult.OK)
            {
                _loadedConfig = new INIFile(SaveFileIni.FileName);
                _loadedConfig["UserSettings"]["txtName"] = txtName.Text;
                _loadedConfig["UserSettings"]["txtSchool"] = txtSchool.Text;
                _loadedConfig["UserSettings"]["txtClass"] = txtClass.Text;
    
                if (chkActiveStudent.Checked == true)
                {
                    _loadedConfig["UserSettings"]["chkActiveStudent"] = "Checked";
                }
                else
                {
                    _loadedConfig["UserSettings"]["chkActiveStudent"] = "UnChecked";
                }
    
                _loadedConfig.Persist();
            }
        }
    }
    

    15. That’s it. Run the app.

    Make some changes to the text on the textbox controls. Save them using the Save INI button.

    You will be prompted for a file name. It can be anything you like (but in this example I used the name of the person I setup in the first textbox. You do not need to enter the ini file extension. You can change the location if you wish.

    Make some more changes to the text in the textBoxes but do not save them. Click on the Open INI button. Browse to the ini file you just saved and open it.

    The text you just modified, without saving, should now be changed to the text you saved into the ini file.