0

I have a catel:TabControl with a custom template, in which I use ContentPresenter to... present the content. But it never appears.

The TabControl is binded to a ObservableCollection of viewModels (inheriting a custom base one).

I don't know what I'm doing wrong in this XAML, but there sure is something; or at least if there's not, I'll know I have to look at my code or something.

<catel:TabControl ItemsSource="{Binding ChildViewModels}" SelectedItem="{Binding SelectedChildViewModel, Mode=TwoWay}">
    <TabControl.Template>
        <ControlTemplate TargetType="{x:Type TabControl}">
            <Grid HorizontalAlignment="Stretch">
                <TabPanel IsItemsHost="True"/>
                <ContentPresenter Content="{Binding SelectedChildViewModel, Converter={catel:ViewModelToViewConverter}}"/>
            </Grid>
        </ControlTemplate>
    </TabControl.Template>
</catel:TabControl>
Kilazur
  • 3,089
  • 1
  • 22
  • 48
  • I accept that the linked 'duplicate' question is not exactly a duplicate of this question, but it does show the more general way of associating view models with views in WPF which will solve the question author's problem. – Sheridan Jun 01 '15 at 12:59
  • I understand; still, I would have liked to know the catel way, which seems way more convenient since I have a bunch of possible viewmodels here, and also because there doesn't seem to be much documentation about this specific converter. – Kilazur Jun 01 '15 at 13:02
  • The way that you describe is flawed... it means that all of the view models must be instantiated at the same time, wasting resources. However, you are welcome to vote to reopen your question using the *reopen* button (next to the *edit* button). – Sheridan Jun 01 '15 at 14:20
  • It's not necessarily a flaw; for example, it allows the user to change his mind (clicked the wrong tab?) without losing data. – Kilazur Jun 01 '15 at 14:59
  • That can also be accomplished without keeping all view models in memory. If you try building a large application like this, you will soon see that it is a big problem... it won't really make much difference in a small scale application though. – Sheridan Jun 02 '15 at 08:00

1 Answers1

1

I recommend to use the LazyLoading mode on the TabControl. In that case, you will only instantiate views when they are really required.

Unless you really need dynamic tabs, I recommend to just embed views and user controls inside the tab control:

<TabItem Header="Item 2">
    <views:MyView2 />
</TabItem>

<TabItem Header="Item 3">
    <views:MyView3 />
</TabItem>

<TabItem Header="Item 4">
    <views:MyView4 />
</TabItem>

Note that in order to create the behavior (LazyLoading, EagerLoader, etc), Catel implements a custom version of the TabControl which might interfere with your ContentPresenter.

Geert van Horrik
  • 5,689
  • 1
  • 18
  • 32
  • Noted! So, if I do need dynamic tabs, how would I do it? Isn't ViewModelToViewConverter the way to go, and if it is, what is wrong in my XAML, preventing it to work? – Kilazur Jun 02 '15 at 07:57
  • Maybe changing it to ContentControl instead of ContentPresenter might fix it. – Geert van Horrik Jun 02 '15 at 08:29