Thursday, April 26, 2007
« Check out i4o: indexing for LINQ | Main | CSLA .NET 3.0 test release #3 available »

I'm confused...

Reading through the WPF docs it is pretty clear that, when building a page-based WPF app, the WPF container (which looks kind of like a stripped down IE) doesn't keep old page instances in memory. So when you click the back button, previous pages are reloaded.

I found this to be the case with one of my pages, where not only did the page reload, but all the data binding was broken when that occurred. So I had to set KeepAlive to true for that page to make it work. That made some sense to me (though I still don't understand why the data binding within the page was all messed up...)

But now I'm finding that other pages are not reloaded. In fact, they are cached in memory, so when I use the Back button to get to them they are showing outdated data.

What a serious pain. I'm sure there are some rules at work behind the scenes here - but I wish the WPF docs were more clear as to what those rules actually were... It appears that the rules are designed to frustrate me: when I want a page to stay in memory it gets reloaded, but when I want a page to reload it stays in memory. Perhaps that's the rule? :)

 

So the problem I'm trying to resolve right now is this:

I have a page showing Project 123. I then navigate to another page, where I'm able to alter some of the data for Project 123. I then use the Back button to get back to the Project 123 page, but it still shows the old data - making it very clear that the page was not reloaded, but rather was cached.

Worse, there doesn't appear to be any nice event raised in a Page object to indicate that it was just navigated to, so I have no way of forcing a refresh of the data. That'd be too easy I guess...

Explicitly setting KeepAlive to false has no affect. And I didn't think it would - false is supposed to be the default value.

And I have double-checked to make sure my code doesn't keep any reference to any pages. But I don't: I just create a page object in a method using a local variable and navigate to it using the WPF navigation service.

 

To be very clear, I actually have a single main page that has a Frame control. My content pages are displayed in this Frame, and my navigation is like this:

   _mainFrame.NavigationService.Navigate(page);

Which does appear to work in all respects, except that page objects are and aren't cached in memory in ways that defy the docs and any rational logic I can see...

Ideas anyone?

Thursday, April 26, 2007 3:15:23 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  | 

Tuesday, May 01, 2007 10:19:36 AM (Central Standard Time, UTC-06:00)
Hi Rocky,
I wanted to see what others responded to your post before I said anything. I get nervous when I hear YOU say "I'm confused" :-). I've been studying your PTracker (for CSLA.NET 3.0). I am curious why you're taking the "Page" approach versus just orienting the application in a WPF Window with Panels. I've studied a lot of recent WPF applications and most have been "Window" based with user controls. I know why the two flavors exist, don't get me wrong. In classic Windows Forms I tended to lean towards developing UI's with panels with injected user controls and controlling the state of the business objects. Is there a reason why that same approach won't work in WPF?

Chris
Chris
Tuesday, May 01, 2007 10:57:09 AM (Central Standard Time, UTC-06:00)
I am using Page because I wanted to see how it worked. The answer, as it turns out, is only so-so... That damn Back button is just as much a PITA in WPF as it is on the web I'm afraid.

I may switch to a user control model, more like my approach in Windows Forms, at some point in here, but I still want to support the Page approach if I can figure it out.
Thursday, May 31, 2007 12:56:46 PM (Central Standard Time, UTC-06:00)
We were doing some investigations on WPF for one of the future versions of our MediaPortal open source project, and we came to the same conclusion:

The navigation mechanism in WPF keeps a reference to your page. So when navigating back to it, its constructor is not called.

Luckily the Loaded event of the Page IS triggered again when navigating back to it. So, the simplest way to solve your problem is to move the code that sets the DataContext of the Page to a Loaded event handler.

Marc
Comments are closed.