AutoWindowPlacement provides ability for WPF to preserve Window position and state between sessions.
$ dotnet add package AutoWindowPlacement.WPFA lightweight library that automatically saves and restores WPF window positions and states between application sessions.
Install via NuGet Package Manager:
Install-Package AutoWindowPlacement.WPF
Or via .NET CLI:
dotnet add package AutoWindowPlacement.WPF
Add the namespace to your Window XAML:
<Window x:Class="YourApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:awp="https://github.com/nullsoftware/AutoWindowPlacement.WPF"
awp:WindowExtensions.PlacementStorageStrategy="{awp:RegistryStorage}"
Title="Main Window" Height="450" Width="800">
<!-- Your window content -->
</Window>
That's it! The window position and state will now be automatically saved to the Windows Registry and restored on next launch.
The simplest way to use AutoWindowPlacement is with the built-in RegistryStorage:
<Window xmlns:awp="https://github.com/nullsoftware/AutoWindowPlacement.WPF"
awp:WindowExtensions.PlacementStorageStrategy="{awp:RegistryStorage}">
</Window>
By default, this stores window placement in:
HKEY_CURRENT_USER\SOFTWARE\{CompanyName}\{ProductName}\{WindowName}.Placement
Customize the registry key and naming format:
<Window awp:WindowExtensions.PlacementStorageStrategy="{awp:RegistryStorage
Key='SOFTWARE\\MyCompany\\MyApp\\WindowSettings',
NameFormat='{0}_Position'}">
</Window>
Implement the IWindowPlacementStorage interface for custom storage:
using System.Windows;
using NullSoftware.Windows;
public class JsonFileStorage : IWindowPlacementStorage
{
private readonly string _filePath;
public JsonFileStorage(string filePath)
{
_filePath = filePath;
}
public byte[]? LoadPlacement(Window window)
{
// Load from JSON file
// Return byte array or null if not found
}
public void SavePlacement(Window window, byte[] serializedPlacement)
{
// Save to JSON file
}
}
Then use it in code-behind:
public MainWindow()
{
InitializeComponent();
WindowExtensions.SetPlacementStorageStrategy(this, new JsonFileStorage("settings.json"));
}
The main class providing attached properties for window placement.
PlacementStorageStrategy - Gets or sets the storage strategy for window placementWindowExtensions.SetPlacementStorageStrategy(window, storageInstance);
IWindowPlacementStorage storage = WindowExtensions.GetPlacementStorageStrategy(window);
Interface for implementing custom storage strategies.
public interface IWindowPlacementStorage
{
void SavePlacement(Window window, byte[] serializedPlacement);
byte[]? LoadPlacement(Window window);
}
Built-in implementation that stores window placement in Windows Registry.
Hive - Registry hive (default: RegistryHive.CurrentUser)Key - Registry key path (default: SOFTWARE\{Company}\{Product})NameFormat - Value name format (default: {0}.Placement)GetSettingKey(Window) - Override to customize the registry value nameProvideDefaultHive() - Override to change default registry hiveProvideDefaultKey() - Override to change default registry key pathLow-level API for direct window placement manipulation.
// Get window placement
var placement = WindowPlacementManager.GetPlacement(window);
// Set window placement
WindowPlacementManager.SetPlacement(window, placement);
// Serialize placement to bytes
byte[] data = WindowPlacementManager.Serialize(placement);
// Deserialize placement from bytes
var placement = WindowPlacementManager.Deserialize(data);
<Window awp:WindowExtensions.PlacementStorageStrategy="{awp:RegistryStorage
Key='SOFTWARE\\MyApp\\Settings',
Hive='CurrentUser'}">
</Window>
public MainWindow()
{
InitializeComponent();
if (Settings.Default.RememberWindowPosition)
{
WindowExtensions.SetPlacementStorageStrategy(this, new RegistryStorage());
}
}
public class CustomRegistryStorage : RegistryStorage
{
protected override string GetSettingKey(Window window)
{
// Use window title instead of type name
return string.Format(NameFormat, window.Title.Replace(" ", "_"));
}
protected override string ProvideDefaultKey()
{
return @"SOFTWARE\MyCompany\MyApp\Windows";
}
}
PlacementStorageStrategy is set, the library hooks into window eventsSourceInitialized, it loads the saved placement and applies it to the windowClosing, it captures the current placement and saves it via the storage strategyThe library automatically detects design-time mode and disables itself in the Visual Studio designer, ensuring a smooth design experience.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
Developed by Null Software