Click here to Skip to main content
11,925,292 members (57,355 online)
Click here to Skip to main content
Add your own
alternative version


59 bookmarked

WPF Persistency

, 3 Jan 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
This article describes how to persist WPF dependency properties


While looking for a way to persist state for a WPF application, I found the article WPF Control State Persistency from Tomer Shamam. Although the article was great and easy to use, I was inspired by a comment from Robert Cannon to try an alternate implementation.

The main differences are:

  • Automatic key generation
  • No need to explicitly load/save persisted data
  • No mode support (Memory/Persist)
  • Only one (static) dictionary for the whole project
  • Direct binding to back storage

Using the code

The following steps have to be done to use the code:

  • Copy attached file UserSettings.cs into your project
  • Add a namespace declaration to the XAML file xmlns:app="clr-namespace:WpfPersist".
  • Use the UserSettings markup extension (and provide default value) where appropriate.

The markup snippet below shows how to use the UserSettings markup extension to store Window Size and Position:

<Window x:Class="WpfPersist.Demo.Window1"
   Height="{app:UserSettings Default=300}" 
   Width="{app:UserSettings Default=400}"
   Top="{app:UserSettings}" Left="{app:UserSettings}"

How it Works?

The main difference between this implementation and the one from Tomer is that I try to automatically derive a key for persistent storage. The snippet below shows how I do that for objects that derive from UIElement:

IUriContext uriContext = (IUriContext)serviceProvider.GetService
key = string.Format("{0}.{1}[{2}].{3}",
   targetObject.GetType().Name, ((UIElement)targetObject).PersistId,

Objects that have a parent in the logical tree (like ColumnDefinition) also can have the key automatically generated:

IUriContext uriContext = (IUriContext)serviceProvider.GetService
UIElement parent = (UIElement)LogicalTreeHelper.GetParent(targetObject);
int i = 0;
foreach (object c in LogicalTreeHelper.GetChildren(parent))
   if (c == targetObject)
      key = string.Format("{0}.{1}[{2}].{3}[{4}].{5}",
         parent.GetType().Name, parent.PersistId,
         targetObject.GetType().Name, i,

Unfortunately I found no way to derive a key for GridViewColumn objects.
For debug builds, the code issues an assert on properties where no key can be generated. In release builds, the code silently ceases functioning.
To work around this, there is a Key property on the markup extension. Note that the key should be unique for the whole project and not only the XAML file. The snippet below shows how to apply the Key property:

   DisplayMemberBinding="{Binding Mode=OneTime,Path=ProcessName}"
   Width="{app:UserSettings Default=100, 
                Key=Window1.ListView0.Col0.Width }" />

Another difference between the two implementations is that I use an ApplicationSettingsBase derived internal class for persistent storage. The current implementation saves the data automatically when the main Window is closing. Meaning that there is no need to provide additional code to save/load the data.

Points of Interest

The biggest shortcoming of this implementation is that I found no way to persist ordering for GridViewColumn's.
For Winforms, the designers provided the DisplayIndex property on the DataGridViewColumn object that could be used for that, but in WPF there is no such thing. The WPF-Designers obviously felt that a modified Columns collection should be enough.

Another issue that nearly drove me nuts was the XmlnsDefinitionAttribute that Tomer is using. It took me quite a while to figure out that this attribute works only for code that is implemented in a different assembly.

If anyone finds a good solution to persist column ordering or finds a way to generate a key for the GridViewColumn property, I'm more than happy to hear about it.

Change Log

  • 7 Aug 2007: Initial Version
  • 3 Jan 2013: Update to VS2010 (recommended fix for VS-Designer)


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Reto Ravasio
Switzerland Switzerland
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionErrors and Warnings Pin
yolki201219-Nov-12 1:52
memberyolki201219-Nov-12 1:52 
AnswerRe: Errors and Warnings Pin
Fernando E. Braz22-Mar-13 8:02
memberFernando E. Braz22-Mar-13 8:02 
GeneralRe: Errors and Warnings Pin
c39209302910-Jun-14 12:13
memberc39209302910-Jun-14 12:13 
BugBug fix : avoid exception in design mode Pin
chprogmer6-Jun-12 4:12
memberchprogmer6-Jun-12 4:12 
As you can see in the demo app, you cannot edit the XAML file in the VS' designer because it causes exceptions in UserSettings.cs

Fortunately this problem is easy to be solved.
Just insert these lines:

if (System.Reflection.Assembly.GetEntryAssembly()==null) // Design mode (the XAML designer called it).
  return ConvertFromString(targetObject, targetProperty, defaultValue);

just before the first occurrence of this line:

if (key == null)

Now you can play with the "default" values and watch the result at real time.

I hope that helps.

Tested with VS 2010, but not in Blend.
GeneralRe: Bug fix : avoid exception in design mode Pin
yolki201219-Nov-12 1:49
memberyolki201219-Nov-12 1:49 
GeneralRe: Bug fix : avoid exception in design mode Pin
chprogmer29-Nov-12 14:44
memberchprogmer29-Nov-12 14:44 
NewsRe: Bug fix : avoid exception in design mode Pin
Reto Ravasio3-Jan-13 15:07
memberReto Ravasio3-Jan-13 15:07 
SuggestionLicense Pin
chprogmer6-Jun-12 1:31
memberchprogmer6-Jun-12 1:31 
GeneralBe carful with PersistId property because it is obsolete Pin
ido.ran24-Jun-10 7:02
memberido.ran24-Jun-10 7:02 
GeneralRe: Be carful with PersistId property because it is obsolete Pin
Reto Ravasio24-Jun-10 12:55
memberReto Ravasio24-Jun-10 12:55 
AnswerRe: Be carful with PersistId property because it is obsolete Pin
Reto Ravasio3-Jan-13 6:02
memberReto Ravasio3-Jan-13 6:02 
GeneralAbout the "Settings" class Pin
Avi Bueno19-Mar-10 15:09
memberAvi Bueno19-Mar-10 15:09 
GeneralRe: About the "Settings" class Pin
Reto Ravasio21-Mar-10 15:13
memberReto Ravasio21-Mar-10 15:13 
GeneralRe: About the "Settings" class Pin
Avi Bueno9-Apr-10 12:20
memberAvi Bueno9-Apr-10 12:20 
GeneralMaking sure owned windows are also persisted Pin
Avi Bueno12-Aug-09 8:00
memberAvi Bueno12-Aug-09 8:00 
AnswerRe: Making sure owned windows are also persisted Pin
Reto Ravasio12-Aug-09 10:37
memberReto Ravasio12-Aug-09 10:37 
GeneralRe: Making sure owned windows are also persisted Pin
Avi Bueno16-Aug-09 22:20
memberAvi Bueno16-Aug-09 22:20 
GeneralKudos + UserSettings DesignTime bug fix Pin
Avi Bueno11-Aug-09 6:41
memberAvi Bueno11-Aug-09 6:41 
GeneralNice code! Help needed with radio btn persistence Pin
mcvf4-Jun-09 12:40
membermcvf4-Jun-09 12:40 
AnswerRe: Nice code! Help needed with radio btn persistence Pin
Reto Ravasio4-Jun-09 13:45
memberReto Ravasio4-Jun-09 13:45 
GeneralBug Pin
Fly17-Aug-08 2:17
memberFly17-Aug-08 2:17 
GeneralRe: Bug Pin
Reto Ravasio19-Aug-08 14:15
memberReto Ravasio19-Aug-08 14:15 
GeneralBug fix for hosting in VS2008 WPF designer Pin
Erwyn7414-Aug-07 6:05
memberErwyn7414-Aug-07 6:05 
GeneralRe: Bug fix for hosting in VS2008 WPF designer Pin
Reto Ravasio15-Aug-07 8:38
memberReto Ravasio15-Aug-07 8:38 
GeneralRe: Bug fix for hosting in VS2008 WPF designer Pin
Dmitriy Sinyagin17-Jul-08 19:40
memberDmitriy Sinyagin17-Jul-08 19:40 
Generalnice. Pin
Michael Sync9-Aug-07 23:03
memberMichael Sync9-Aug-07 23:03 
GeneralVery good! Pin
Super Lloyd7-Aug-07 16:58
memberSuper Lloyd7-Aug-07 16:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.151126.1 | Last Updated 3 Jan 2013
Article Copyright 2007 by Reto Ravasio
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid