I like the main window of my applications to "remember" its position, size and state. I want a no fuss method to add this functionality to my projects.
This article presents a class that provides this functionality using attached properties. The attached properties method provides a solution that does not involve subclassing the window. This solution does not require any code to be placed in the windows "code behind" file, hence keeping good separation of presentation and business layers. My solution is applied to my WPF project with the addition of a couple of lines of XAML.
This code was written and tested against the June 2006 CTP of the .NET Framework 3.0.
Using the code
One of the goals of the code is that it is easy to use. Because of this, I am going to start off by explaining how to use it and then follow up by explaining how it works.
- Create a new WinFX Windows Application with Visual Studio 2005 and add a reference to the Kingsmill.Windows.dll assembly.
- Open Window1.xaml and view the XAML; it should look like this:
Title="WindowsApplication1 "Height="300" Width="300">
- Edit Window1.xaml as per the following:
Title="WindowsApplication1 "Height="300" Width="300"
- Run and stop the application, resizing and repositioning the window a few times. Note that the window size position and state is now "remembered".
How it works
The solution is implemented within the
What we are doing here is adding some behavior to the Avalon
Window by adding some event handlers, but without subclassing the
Window. The Avalon property system allows us to register a property that can be attached to any element; in our case the
Window element. This is the same mechanism that allows us to put XAML code like
DockPanel.Dock="Top" on a
Button inside a
DockPanel, even though
Dock isn't a property that buttons know about. We can also make use of the ability to register for a callback when the property changes.
Here is our code that registers the
Save property and registers the
OnSaveInvalidated callback that is executed when the
Save property value is changed.
public static readonly DependencyProperty SaveProperty
= DependencyProperty.RegisterAttached("Save", typeof(bool),
typeof(WindowSettings), new FrameworkPropertyMetadata
and here is the callback:
private static void OnSaveInvalidated(DependencyObject
dependencyObject, DependencyPropertyChangedEventArgs e)
Window window = dependencyObject as Window;
if (window != null)
WindowSettings settings = new WindowSettings(window);
The method above is called in response to our XAML line:
OnSaveInvalidated method, we see that the
dependencyObject is a
e.NewValue = true and a new
WindowSettings object is created that wraps our
Attach() method is then called which attaches our desired
Save behavior to the Avalon
Window by attaching some event handlers whose responsibility it is to call the
SaveWindowState() methods when the
Window is initialized and closed.
Well, that's about all there is to it. The rest of the code deals with saving and loading the settings and that has been discussed in other articles and is nothing new.