Click here to Skip to main content
Licence 
First Posted 7 Aug 2007
Views 32,449
Downloads 194
Bookmarked 40 times

WPF Persistency

By | 7 Aug 2007 | Article
This article describes how to persist WPF dependency properties

Introduction

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"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:app="clr-namespace:WpfPersist"
   Title="WpfPersist.Demo"
   Height="{app:UserSettings Default=300}" 
   Width="{app:UserSettings Default=400}"
   Top="{app:UserSettings}" Left="{app:UserSettings}"
   >
   <Grid>
   ...
   </Grid>
</Window>

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
                            (typeof(IUriContext));
key = string.Format("{0}.{1}[{2}].{3}",
   uriContext.BaseUri.PathAndQuery,
   targetObject.GetType().Name, ((UIElement)targetObject).PersistId,
   targetProperty.Name);

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

IUriContext uriContext = (IUriContext)serviceProvider.GetService
                            (typeof(IUriContext));
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}",
         uriContext.BaseUri.PathAndQuery,
         parent.GetType().Name, parent.PersistId,
         targetObject.GetType().Name, i,
         targetProperty.Name);
      break;
   }
   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:

<GridViewColumn
   DisplayMemberBinding="{Binding Mode=OneTime,Path=ProcessName}"
   Header="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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Reto Ravasio



Switzerland Switzerland

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralBe carful with PersistId property because it is obsolete Pinmemberido.ran6:02 24 Jun '10  
GeneralRe: Be carful with PersistId property because it is obsolete PinmemberReto Ravasio11:55 24 Jun '10  
GeneralAbout the "Settings" class PinmemberAvi Bueno14:09 19 Mar '10  
GeneralRe: About the "Settings" class PinmemberReto Ravasio14:13 21 Mar '10  
GeneralRe: About the "Settings" class PinmemberAvi Bueno11:20 9 Apr '10  
GeneralMaking sure owned windows are also persisted PinmemberAvi Bueno7:00 12 Aug '09  
AnswerRe: Making sure owned windows are also persisted PinmemberReto Ravasio9:37 12 Aug '09  
GeneralRe: Making sure owned windows are also persisted PinmemberAvi Bueno21:20 16 Aug '09  
GeneralKudos + UserSettings DesignTime bug fix PinmemberAvi Bueno5:41 11 Aug '09  
GeneralNice code! Help needed with radio btn persistence Pinmembermcvf11:40 4 Jun '09  
AnswerRe: Nice code! Help needed with radio btn persistence PinmemberReto Ravasio12:45 4 Jun '09  
GeneralBug PinmemberFly1:17 17 Aug '08  
GeneralRe: Bug PinmemberReto Ravasio13:15 19 Aug '08  
GeneralBug fix for hosting in VS2008 WPF designer PinmemberErwyn745:05 14 Aug '07  
GeneralRe: Bug fix for hosting in VS2008 WPF designer PinmemberReto Ravasio7:38 15 Aug '07  
GeneralRe: Bug fix for hosting in VS2008 WPF designer PinmemberDmitriy Sinyagin18:40 17 Jul '08  
Generalnice. PinmemberMichael Sync22:03 9 Aug '07  
GeneralVery good! PinmemberSuper Lloyd15:58 7 Aug '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 7 Aug 2007
Article Copyright 2007 by Reto Ravasio
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid