While I was on vacation, Seema blogged that WPF will not have hardware acceleration for layered windows on Windows XP. Nick elaborates a bit to explain that while we did once have partial support for this, it was unreliable and sometimes slower than software rendering. Rest assured that hardware acceleration is still there for Vista. If you have any questions, Seema is the expert.
Author: lauren
How Controls Retain Their State when You Navigate Away
Over on Bea’s excellent blog, Sam asked a great question about how controls retain their state when you navigate away from a page:
This got nothing to do with threads, sorry for intruding, but I don’t know where to ask this question (managed newsgroups provide no answer)
When you navigate back in a browser-like WPF application, the pages are re-created (at least the constructor is called).
And somehow, magically, the content for Textbox(es) in the page will be filled with whatever had been in there when the page had been left.
Since the page is created anew on navigating ‘Back’, where does this content come from? Is it bound to some kind of session storage as default?
And how do I get my own values back (as content for Listboxes for example are lost on navigating)?
thanks, Sam!
First of all, Sam, I am sorry that no one answered your newsgroup question. I just returned from a long vacation and I hope that this delayed response is still helpful.
Understanding how control state is retained requires a bit of knowledge of how “journaling” works. Journaling is the mechanism for keeping track of the user’s navigation history – the “Journal” is an internal data structure which consists, among other things, of a ForwardStack and BackStack (these stacks are exposed on Frame and NavigationWindow). As a user navigates through a set of pages (say by clicking on Hyperlinks that point to other pages), JournalEntries are added to the BackStack. Specifically, a BackStack entry for a page is added upon navigating away from the page. If the user clicks on the back button, a few things happen: a JournalEntry is popped off the BackStack, the page it represents is rehydrated, the framework navigates to the rehydrated page, and a JournalEntry for the current page is created and added to the ForwardStack. If a user initiates a new navigation, the forward stack is cleared.
This system is modeled after how navigation works in all popular web browsers today, and you will notice that WPF navigation works the same way that navigation works in Internet Explorer, for example.
There are two main ways that JournalEntries are created, depending on what is being journaled (and also on the value of the KeepAlive property, which I will discuss in a moment):
- By URI: If you navigate to a XAML page via its source URI (e.g. page1.xaml), and then navigate away from it, the page is stored simply by creating a new JournalEntry that stores the URI for that page (the JournalEntry.Source property is used for this purpose). Navigating back to the page simply requires the framework to get the Source and navigate to it.
- By object: If you navigate to an object rather than a XAML page (e.g. by creating an object tree programmatically and calling Navigate(object content)), and then navigate away from it, we cannot journal by URI because there is no URI (!). In this case, the object tree is kept alive and a reference to the tree is stored in its JournalEntry. Navigating back to the page involves re-attaching the saved tree as the Content of the Frame or NavigationWindow.
The default behavior for journaling pages that have URIs is by URI, but this can be overridden by setting JournalEntry.KeepAlive (which is an attached DP) if desired. Keep in mind that there are working set implications when you use KeepAlive, because the whole page really is kept alive in memory. URI JournalEntries are, of course, smaller.
At this point, it is probably obvious to you that when we journal “by object,” storing the user-modified state of controls (like TextBoxes and RadioButtons) is trivial: because the whole tree is kept alive, there is no additional work to do. When we journal by URI, we traverse the tree and look for controls that have properties which should be journaled. We store these property values in the JournalEntry along with the source URI for the page. We know which properties should be journaled because they have set the FrameworkPropertyMetadataOptions.Journal flag. Also note that we will ignore controls which do not have the PersistId property set. When a page is rehydrated from a JournalEntry, we navigate to the JournalEntry.Source URI and we apply all of the deltas to control state that we have stored in the Journal.
In general, controls whose state may be changed via user interaction maintain their state across navigations (there are notable exceptions, like PasswordBox). When authoring custom controls, you should consider whether or not your controls have state that may be modified via user interaction, and if they can, then you should usually mark those properties with FrameworkPropertyMetadataOptions.Journal and set the PersistId. If your control stores sensitive data like a password or credit card number, you will likely not want that state to be journaled.
Sam, I did not understand the last part of your question, about ListBox. Could you elaborate or send me an example of some source code that is not behaving as expected?
Windows Vista RC1
I have the RC1 build of Windows Vista running on an old-ish machine at work – the machine has 512 MB of RAM, which means that my Windows Experience Index is a measly 2.9. Given that, I was pleasantly surprised to find that the OS is quite zippy, and not to mention extremely fun to use! It’s very exciting to see how much the performance and polish are improving with every build. You can download RC1 from here.
Kenny is a Great Sport
Wine Tasting Lunch at Castello di Gabbiano
As a wedding gift, Vidya and John got us a wine tasting lunch and cellar tour at a castle/vineyard called Castello di Gabbiano in the hills outside of Florence. After plotting out our course on the map, we got into our trusty little rental car from a good av rental company and ventured out into the Tuscan hills.
We arrived early at the castle, so we had some time to tour around ourselves before our scheduled tour of the cellars. The castle and wine cellars date back to the 12th century, although additions were made to the structure over the following centuries.
After our tour of the castle grounds and the wine cellars, we had lunch on the patio, including several courses and a wine pairing. My favorite course was the vin santo with cantucci (cookies very similar to biscotti, for dipping in the vin santo).
We were a bit tipsy after lunch, so we took a nap for about an hour on a couch inside the castle before continuing on our little car ride around Tuscany.
All in all, it was an extremely fun way to spend an afternoon in Tuscany and a great present!