views:

922

answers:

3

I'm creating an WPF application using the MVVM framework, and I've adopted several features from Josh Smith's article on MVVM here...

Most importantly, I'm binding a TabControl to an ObservableCollection of ViewModels. This means that am using a tabbed MDI interface that displays a UserControl as the content of a TabItem. The issue I'm seeing in my application is that when I have several tabs and I flip back and forth between tabs, the content is being refersh each time I change tabs.

If you download Josh Smith's source code, you'll see that his app has the same problem. For example, click on the "View All Customers" button and scroll down to the bottom the ListView. Next click on the "Create New Customer" button. When you switch back to the All Customer view you'll notice that the ListView scrolls back to the top. If you switch back to the New Customer tab and place your cursor in one of the TextBoxes, then switch to All Customers tab and back, you'll notice that the cursor is now gone.

I imagine that this is because I'm using an ObservableCollection, but I can't be sure. Is there any way to prevent the tab's content from refreshing when it receives the focus?

EDIT: I found my problem when I ran the profiler on my application. I'm defining a DataTemplate for my ViewModels so it knows how to render the ViewModel when it is displayed in the tab... like so:

<DataTemplate DataType="{x:Type vm:CustomerViewModel}">
    <vw:CustomerView/>
</DataTemplate>

So whenever I switch to a different tab, it has to re-create the ViewModel again. I fixed it temporarily by changing my ObservableCollection of ViewModels to an ObservableCollection of UserControls. However, I would really still like to use DataTemplates if possible. Is there a way to make a DataTemplate work?

A: 

I believe this has something to do with binding mode- did you try {Binding Mode=OneWay}? Also binding to any of the 'DataSource' objects will cause the same issue.

Im not sure if oneway binding will be the desired behavior you are looking for but i would start there.

J Rothe
I tried that, but it didn't work. I've updated my question... let me know if you can give any input. Thanks.
Brent
A: 

It has nothing to do with the ObservableCollection. It’s because the View for the Customer is reused instead that WPF creates a new View for every Customer.

You might have a look at the Writer sample application of the WPF Application Framework (WAF). It implements the TabControl for a tabbed MDI interface as well but doesn’t suffer from the issue you mentioned in your post. The issue is solved in Writer by creating an own UserControl for every document ‘tab’.

jbe
Thanks @jbe, I know that I could solve the problem using an ObservableCollection of UserControls, but I'd prefer to use an ObservableCollection of ViewModels if possible. I've updated my question... let me know if you can give any input. Thanks.
Brent
When I started with the MVVM pattern I have used the DataTemplate mechanism of WPF as well for wiring the View with the ViewModel together. But I ran into a few issues like the one you mention here. That’s the reason why I wire them with MEF together. WPF just gets the Views (UserControls) and so I don’t need the DataTemplate for this scenario anymore.
jbe
+2  A: 

Here is a solution that creates a subclass of the TabControl. http://eric.burke.name/dotnetmania/2009/04/26/22.09.28

This seems to work well and only loads the content once the tab is selected. It worked for me. Let me know how you get on.

Eli Perpinyal
Hey that's interesting... I'll have to try it out. Thanks for the link!
Brent