views:

52

answers:

6

I have a complex form to allow the user to configure my app.

What's the best way to save the form state & reload when the program next runs.

I mean text he has entered in list boxes, the selected item of combo/list/radio, whether a checkbox is cheeked, etc

A: 
Private Sub frm_Closing (sender as Object, e as CancelEventArgs) Handles MyBase.Closing

   ' save all the values you want'

End Sub

Private Sub frm_Load(sender as Object, e as EventArgs) Handles MyBase.Load

   If SaveSettingsExist Then
      ' restore all the values you want'
   End If

End Sub
Bill
Mawg
A: 

You have a few options of where to save the entered settings - in a configuration file, or in the registry, maybe a database (maybe even "the cloud", but i won't go there).

You should have the user carry out a specific action (such as clicking an Apply button) before you save the settings - you shouldn't just save the settings when the user closes the form, as that is ultimately not good UX.

How you persist the settings is totally up to you - you can save them into a straight name/value pair style config file, you may want to use XML in the config file, or you save them as keys and values in a known spot in the registry (or you could save name/value pairs into a database table).

When your application is next run, one of the start up tasks can be to check the known location (whether it be the registry or a config file) for the settings, and then load them into a settings class. Make sure that you have logical default values for each setting in case it has either never been set, or for some reason you cannot read it back in. The settings class can then either be passed in to each form for it to apply whatever settings are relevant, or it could be a static class (globally visible single instance class) so that it can just be read from anywhere in the application.

Edit: after reading your comment to another answer, here is another option, slightly more advanced. Use the settings class i mentioned earlier, but also use binding - you can bind your settings object directly to your form, so any values entered will be updated directly into the settings object without you having to write code to do it (provided you use two way binding). The "streaming" can be achieved by serializing the settings object to a file (or a database), i suggest you look at the XmlSerializer.

slugster
A: 

I actually have a couple of generic routines I use like this for saving the form size/position and ListView column settings. So I have something like...

Private Sub frm_Closing (sender as Object, e as CancelEventArgs) Handles MyBase.Closing

   SaveFormPos(Me)
   SaveListview(Me, lvuInvoices)

End Sub

Private Sub frm_Load(sender as Object, e as EventArgs) Handles MyBase.Load

   RestoreFormPos(Me)
   RestoreListview(Me, lvuInvoices)

End Sub

The Me parameter (for the Listview routine) is used to create a key for the values to be saved to the registry. You have all sorts of options in front of you. You could put this functionality into a base class for all your Forms, create a SaveState class, or simply stick routines into a Module. You could save this data to the registry, a database, text files. You could have a generic routine that trawls through the Controls collection looking for TextBoxes, Checkboxes etc.

However, once you've created a useful set of save routines, you can then employ them on any subsequent form you want, so you only need to do the hard work once.

Bill
A: 

I also agree on having a LoadSettings/SaveSettings set of functions that are called when creating the form/ when closing the application.

As a store location for the application's settings I recommend using the Isolated Storage.

As an addition, depending on the controls you are using on your form, you could have the options of saving their status in XML format format and then restoring it next time. For example Infragistics controls offer this possibility(e.g UltraDockManager, UltraToolbarManager have a SaveAsXml/LoadFromXml pair of functions).

Ando
A: 

Serialize the Form.

Implement ISerializable, and in serializable constructor and GetObject() method load/save your fields.

In OnClosing serialize the form.

    /// 
    /// try to obtain the las serialized main form with old data
    MainForm mainForm = DeserializeMainForm("mainForm.data");
    ///
    /// if any old data found, create a new(empty) main form
    if (mainForm == null) mainForm = new MainForm();

    static MainForm DeserializeMainForm(string filePath)
    {
        MainForm mf = null;
        FileStream fileStream = null;
        try
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            fileStream = new FileStream(filePath, FileMode.Open);
            mf = (MainForm)binaryFormatter.Deserialize(fileStream);
        }
        catch { }
        finally
        {
            if (fileStream != null)
            {
                fileStream.Close();
            }
        }

        return mf;
    }

MainForm:

[Serializable]
public partial class MainForm : Form, ISerializable
{
        protected MainForm(SerializationInfo info, StreamingContext context)
        : this()
    {
        if (info == null)
            throw new System.ArgumentNullException("info");

        this.tbxServerIp.Text = info.GetString("server ip");
        this.tbxServerPort.Text = info.GetString("server port");
        this.tbxEventFilter.Text = info.GetString("event filter");
        this.tbxWallId.Text = info.GetString("wallId");

        foreach (Control control in this.Controls)
        {
            if (control is EventSender)
            {
                EventSender eventSender = (control as EventSender);
                eventSender.LoadFromSerializationInfo(info);
            }
        }   
    }

    private void SerializeThis()
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        FileStream fileStream = new FileStream("mainForm.data", FileMode.Create);
        try
        {
            binaryFormatter.Serialize(fileStream, this);
        }
        catch
        {
            throw;
        }
        finally
        {
            fileStream.Close();
        }
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        SerializeThis();
        base.OnClosing(e);
    }
}
serhio
A: 

Lots of people here telling me when to save, but not many telling me how ...

In the end I went with WritePrivateProfileString()

Mawg