A very common requirement for Windows Forms applications is the ability to 'remember' the location and size of forms when they are closed, so that the next time they are shown, they can be restored to the former position. The Application Settings feature is .NET 2.0 makes it simple to do this, but unfortunately, it is a little hard to get it 'just right'. This question is asked frequently on internal and external Microsoft forums, so I thought it warranted a blog post.
Now, the Windows Forms designer in Visual Studio 2005 provides a simple UI to data bind properties on controls to application settings. So the first thing that might occur to you is to simply bind the Form's Location and Size properties to settings, add a line of code to save the settings class, and that's it! Unfortunately, this is not the best option for a few reasons:
- First of all, you may notice that the Form.Size property is not offered up in the settings binding UI. This is because this property is marked DesignerSerializationVisibility.Hidden, so the designer doesn't know how to serialize it, let alone generate a data binding for it. Instead, for Form, the ClientSize property is the one that gets serialized.
- So okay, maybe you can bind Location and ClientSize then? Well, yes, but this has another problem. Try setting it up and then attempt to resize the form from the left or top edge. You will see weird behavior. Why is this? It is beyond the scope of this post to give the full explanation, but it suffices to say that it has to do with how two way data binding works in the context of property sets that mutually affect each other (in the case of Location and ClientSize, both eventually call into a common method, SetBoundsCore()).
- This solution does not do the 'right' thing in the situation when the user maximized the form before closing it. In this case, you probably want to remember that the form was maximized, but also keep track of the last location/size before it was maximized, so you can restore it the next time the user hits the Restore button. You may want to handle the minimize case in a similar way too. The simple data binding solution does not do this right.
- Data binding to properties like Location and Size is just not efficient. Each time the user moves the form or resizes it, Windows sends hundreds of messages to the form, causing the data binding logic to do a lot of processing, when all you want is just to store the last position and size before the form is closed.
The good news is that this is very easy to do with a few lines of code:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
Properties.Settings.Default.MyState = this.WindowState;
if (this.WindowState == FormWindowState.Normal)
Properties.Settings.Default.MySize = this.Size;
Properties.Settings.Default.MyLoc = this.Location;
Properties.Settings.Default.MySize = this.RestoreBounds.Size;
Properties.Settings.Default.MyLoc = this.RestoreBounds.Location;
private void Form1_Load(object sender, EventArgs e)
this.Size = Properties.Settings.Default.MySize;
this.Location = Properties.Settings.Default.MyLoc;
this.WindowState = Properties.Settings.Default.MyState;