1

I know, that this topic has been discussed many times, so straight to the point.

This is the ItemsSource of TabControl:

Tabs = new ObservableCollection<aTabViewModel>
{
    new HomeViewModel(),
    new StatisticsViewModel()
};

Here is the TabControl itself

<TabControl ItemsSource="{Binding Tabs}">
<TabControl.Resources>
    <DataTemplate DataType="{x:Type pagesVM:HomeViewModel}">
        <pages:Home/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type pagesVM:StatisticsViewModel}">
        <pages:Statistics/>
    </DataTemplate>
</TabControl.Resources>

<TabControl.ItemContainerStyle>
    <Style BasedOn="{StaticResource MetroTabItem}" TargetType="TabItem">
        <Setter Property="Header" Value="{Binding Header}" />
    </Style>
</TabControl.ItemContainerStyle>

HomeViewModel and StatisticsViewModel are instantiated first time when we add them to Tabs collection, and second time when we select tab in a application (which is seems to be a behaviour of TabControl). And this double-loading apparently isn't right thing.

Q: How can I make my tabs load only when selected?

Community
  • 1
  • 1
  • I don't think the VMs are instantiated more than once. – H.B. Jul 08 '16 at 17:42
  • Make the ItemsSource of the TabControl List hold the Tabs Titles, add string Property in the ViewModel to Hold the Selected Tab, in the Setter of the SelectedTab check the new Selection and create its DataContext if the Tab Loaded so just assign it. – Henka Programmer Jul 08 '16 at 17:42
  • @H.B. I'm sure as hell it does. This happens right after i select a tab in app, and I'm pretty sure there is no other reason for this. Besides, linked questions state the same – Stanley Russian Jul 08 '16 at 17:56
  • @HenkaProgrammer I got what you talking about, but I wonder if there's more elegant solution. I mean, selecting a tab calls assigned constructor just fine, there should be the way not to call it beforehand – Stanley Russian Jul 08 '16 at 18:04
  • 1
    Pretty sure you got view-model and view confused, it is rather *impossible* for the VMs to be created by anything the tab control does here. – H.B. Jul 08 '16 at 18:13
  • 2
    @StanleyRussian He's right, TabControls don't do that all by themselves. That said, one solution to this is not to have the viewmodels load any data when you create them. Instead, they implement an interface ILazyLoad that has a LazyLoad() method which loads the vm's stuff *if* it hasn't already been loaded. Then in codebehind in TabControl_SelectionChanged, grab the new tab's DataContext, and if it implements ILazyLoad, cast and call. – 15ee8f99-57ff-4f92-890c-b56153 Jul 08 '16 at 18:14
  • 1
    [This is a nicer solution](http://stackoverflow.com/a/4756755/424129). – 15ee8f99-57ff-4f92-890c-b56153 Jul 08 '16 at 18:16
  • Well, if you say so. Btw, I already tried [suggested](http://stackoverflow.com/a/4756755/424129) way aswell, and ran into whole another problem which is out of scope here. – Stanley Russian Jul 08 '16 at 18:53
  • Thanks for help anyway. – Stanley Russian Jul 08 '16 at 19:00
  • @StanleyRussian Did you ask for help with the other problem? – 15ee8f99-57ff-4f92-890c-b56153 Jul 09 '16 at 02:34
  • @EdPlunkett Whatever was it in the time of our conversation I figured it out, works as a charm with a solution you provided. If you want, you can remake your comment into an answer so I can mark it as accepted. – Stanley Russian Jul 15 '16 at 17:34

1 Answers1

2

How can I make my tabs load only when selected?

Put in such load logic in the GotFocus event on the tab page with checks to verify that the DataContext is only loaded once.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122