Any application that people use often should be as convenient as possible. One of the most expected conveniences of a desktop application is that the size, location, and state of the application’s various windows persist across runs. If I resize a window, move it to the left side of my screen, and then close it, the next time I open that window it should be the same size and be at the same place on the left side of the screen. It would be great if WPF provided that functionality for us, but it does not. This post introduces a base window class that automates this for us, so that every window in our applications gets this functionality free.
What is involved?
The recipe for this dish involves:
- 1 lbs of an abstract window subclass called ConfigurableWindow
- 1 cup of a ConfigurableWindowSettings class that knows how to load and save the window settings
- 1 dash of a ConfigurableWindow subclass which overrides the CreateSettings method and returns a ConfigurableWindowSettings object
- 4 delicious properties in the Settings.settings file that are used to persist the window settings
This recipe serves one window. For every additional window that needs to have its settings persisted, add three more properties to the Settings.settings file, and create a new ConfigurableWindowSettings object that knows how to get and set those values.
How to use it
It is easy to use the ConfigurableWindow class. Here is a step-by-step explanation of how the demo application (available for download at the end of this post) was put together. This walkthrough assumes that you already have a WPF project set up and you’ve included the source files for the ConfigurableWindow and ConfigurableWindowSettings classes.
First, create a new Window in your WPF project. In this case, I named it DemoWindow.
Change DemoWindow so that it derives from ConfigurableWindow. Note: you need to do this both in the code and XAML file. Here is how you do it in the XAML:
Now that DemoWindow derives from ConfigurableWindow you need to override the CreateSettings method, and return an IConfigurableWindowSettings object. Here is that method:
At this point, if you compile the project you will receive an error telling you that the DemoWindowConfigSettings class does not exist. To remedy this situation, add a nested class in DemoWindow as seen below:
There are several things to notice about that class. First, it derives from ConfigurableWindowSettings, which is a class that knows how to load and save window settings across runs of an application. We pass into the base constructor five pieces of information: the backing store for all persisted property settings, and four property names. Those property names correspond to settings that we will soon add to our application’s Settings.settings file. Also, the DemoWindowConfigSettings class hooks the DemoWindow’s Closed event and sets the IsFirstRun setting to false. This is necessary because it enables ConfigurableWindow to know if the persisted window location value is a value saved from a previous run or not.
Lastly, we need to add some settings into the project’s Settings.settings file. We need to add four items, as seen below:
If you add more windows that derive from ConfigurableWindow, you only need to add the last three properties again with new names. The IsFirstRun setting only needs to exist once since it applies to the entire application, not a specific window in the application.
Word of warning
If you run the application in debug mode (F5) you will be using a different config file than if you run without a debugger attached (Ctrl + F5). This is the way things work in Visual Studio, so don’t be surprised if you stumble across this.
Get the code
Download the demo project here: Configurable Window Demo (The source code was updated on 12/28/07). Be sure to change the file extension from .DOC to .ZIP and then decompress the file. Note, this project was built in Visual Studio 2008, so you will have to copy the source files into a new project if you are using VS2005.