You may have noticed in the past that the WPF Frame element didn’t work very well when hosted in a Window (it worked just fine in a NavigationWindow or in a Page hosted in the browser). The Frame could navigate to content, but there was no way to navigate forward or back, as you could do with a Frame hosted in a NavigationWindow. This wasn’t just because there was no navigation UI associated with the Frame, but because the Frame had no Journal of its own; that is, there was no bookkeeping mechanism to record the navigations.
The reason that Frame didn’t have a Journal is somewhat historical — WPF Frames don’t have their own Journals because HTML frames don’t have their own travel logs. In HTML, a frame’s navigation history is recorded by the travel log associated with the top-level page. That is why clicking on the back and forward buttons on the browser may cause either the top-level browser window or a frame to navigate — it depends on what is at the top of the travel log’s “back stack”. WPF Frames work the same way for consistency, and in most cases, this is the behavior people want.
But there were a few holes in this story. In particular:
- What if you wanted to host a Frame inside a (non-navigation) Window, to provide a region of navigable content on a page?
- What if you wanted to have Frames whose navigation was independent of the top-level navigation container?
The answer to both of these questions was the same: roll your own. And rolling your own wasn’t easy.
To address this, we added a new property to Frame that enables Frame to have its own Journal. The property is called JournalOwnership, and there is a JournalOwnership enum with three values: Automatic, OwnsJournal, and UsesParentJournal. These properties behave as follows:
- Automatic – Whether or not this Frame has its own Journal depends on its parent. If the Frame is hosted by a Frame or NavigationWindow, it behaves as though UsesParentJournal was set. If it is not hosted by a Frame or NavigationWindow, it behaves as though OwnsJournal was set.
- OwnsJournal – The Frame has its own Journal which operates independent of the hosting navigatorâ€™s Journal (if it has one).
- UsesParentJournal – The Frameâ€™s JournalEntries are merged into the hosting navigator’s Journal. If the hosting navigator does not have a Journal, then no journaling occurs for this Frame.
Around here, we started affectionately calling a Frame that has its own Journal an “Island Frame”. The name stuck, and now everyone on my team uses it (and it’s much easier than saying “a Frame that has Frame.JournalOwnership=JournalOwnership.OwnsJournal”).
The other detail that falls out of providing this property is that you may want to provide some navigation UI on an independent Frame, to control the navigations that occur inside that Frame. For this, we added a NavigationUIVisibility property on Frame, whose default value will show navigation UI if the Frame has its own Journal, and will not show navigation UI if the Frame shares a Journal with a parent navigator.
If this all sounds somewhat obscure and theoretical, hopefully my next post (a cool application of Island Frames) will help illuminate the possibilities a little better…