.NET WPF Remember window size between sessions
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When a user resizes your WPF window, arranges it on their second monitor, and then closes and reopens the application, they expect the window to appear exactly where they left it. Failing to persist window size and position is a small usability issue that creates a constant source of friction. WPF provides a built-in settings infrastructure through Properties.Settings that makes this straightforward to implement, requiring no external libraries or databases.
Why Properties.Settings Is the Right Tool
Before reaching for a JSON file or the Windows Registry, consider that .NET already includes a settings system designed specifically for this use case. Properties.Settings stores user-scoped values in a per-user XML file under AppData/Local, survives application updates, and requires no file I/O boilerplate. For window position data, this is the simplest and most idiomatic approach.
Creating the Settings
Open your project's Properties/Settings.settings file (or create one through Project Properties, then the Settings tab). Add four user-scoped settings:
| Name | Type | Scope | Default |
| WindowTop | double | User | 100 |
| WindowLeft | double | User | 100 |
| WindowHeight | double | User | 450 |
| WindowWidth | double | User | 800 |
User scope is essential here. Application-scoped settings are read-only at runtime, so they cannot be saved.
Restoring Window State on Load
In your MainWindow.xaml.cs, handle the Window.Loaded event (or use the constructor after InitializeComponent) to restore the saved values:
This sets the window's position and size to whatever was saved during the last session. On the very first run, the default values from the Settings file are used.
Saving Window State on Close
Handle the Window.Closing event to persist the current values before the application exits:
The Save() call writes the values to the user's configuration file on disk. Without this call, the in-memory changes are discarded.
Using XAML Bindings Instead
If you prefer a declarative approach, you can bind window properties directly in XAML. First, add a namespace reference to your settings, then bind each property:
With two-way bindings, the settings are updated automatically as the user resizes or moves the window. You still need to call Properties.Settings.Default.Save() in the Closing handler to persist to disk.
Handling Multi-Monitor Scenarios
A saved window position can become invalid if the user disconnects a monitor. Restoring the window to coordinates that are off-screen results in an invisible window. Add a validation step after restoring:
This checks whether the restored window rectangle intersects with any available screen. If not, it resets to safe default values. You need a reference to System.Windows.Forms for the Screen class.
Persisting Window State (Maximized, Normal)
Users also expect the maximized state to be remembered. Add a WindowState setting of type int (User scope, default 0) and save it alongside the position:
Note that size and position are only saved when the window is in the Normal state. If the window is maximized, Top, Left, Height, and Width reflect the maximized bounds, not the user's intended normal-state dimensions.
Alternative Approaches
While Properties.Settings works well for most cases, alternatives exist. For .NET Core/.NET 5+ projects where Properties.Settings may not be available, serialize a settings object to a JSON file using System.Text.Json. You can also store values in the Windows Registry under HKEY_CURRENT_USER, though this ties your application to Windows and complicates uninstall cleanup.
Common Pitfalls
- Using Application scope instead of User scope: Application-scoped settings are read-only at runtime. Your
Save()call will silently do nothing. - Forgetting to call
Save(): In-memory changes are lost when the application exits. Always callSave()explicitly. - Not handling off-screen positions: A saved position from a disconnected monitor makes the window invisible on next launch.
- Saving size while maximized: The
Top,Left,Height, andWidthvalues of a maximized window are the maximized bounds, not the restore bounds. Always checkWindowStatebefore saving dimensions. - Not handling first-run gracefully: Ensure your default settings in the Settings file produce a reasonable window size and position.
Summary
- Use
Properties.Settings.Defaultwith User-scoped settings to persist window size and position between sessions. - Save on the
Closingevent and restore on theLoadedevent, or use two-way XAML bindings. - Validate restored positions against available monitors to prevent invisible windows.
- Save
WindowStateseparately and only persist size/position when the window is inNormalstate. - For .NET Core/.NET 5+ projects, consider a JSON file as an alternative to the traditional
Properties.Settingsmechanism.

