Create TabItems with different UserControl's i

2019-08-18 16:56发布

问题:

First of all, I'm kind new to WPF and MVVM, so you can expect some crazy mix here, just suggest changes, I'm here to learn.
This question comes as continuation of this one.

I have a TabControl with some TabItem's defined in XAML each of them has his own UserControl.
XAML

<Window x:Class="WPF.GUI.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:viewModels="clr-namespace:WPF.GUI.ViewModels"
        xmlns:views="clr-namespace:WPF.GUI.Views"
        xmlns:mainWindow="clr-namespace:WPF.GUI.ViewModels.MainWindow"
        xmlns:model="clr-namespace:WPF.Processing.Model"
        xmlns:helpers="clr-namespace:WPF.GUI.Helpers"
        mc:Ignorable="d">

    <!--#region Resources-->
    <Window.Resources>
        <DataTemplate DataType="{x:Type viewModels:ResultViewModel}">
            <views:ResultView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModels:ConfigurationViewModel}">
            <views:ConfigurationView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModels:DetailedViewModel}">
            <views:DetailedView />
        </DataTemplate>
    </Window.Resources>
    <!--#endregion Resources-->

    <!--#region DataContext-->
    <Window.DataContext>
        <mainWindow:MainWindowViewModel />
    </Window.DataContext>
    <!--#endregion DataContext-->

    <!--#region Main Grid-->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!--#region Tabs-->
        <TabControl>
            <TabControl.Resources>
                <CollectionViewSource Source="{Binding Model.TabItemsVM}" x:Key="Tabs"/>
                <DataTemplate DataType="{x:Type helpers:VMWrap}">
                    <ContentPresenter Content="{Binding VModel}"/>
                </DataTemplate>
            </TabControl.Resources>
            <TabControl.ItemsSource>
                <CompositeCollection>

                    <!--Result Tab-->
                    <TabItem Header="Result">
                        <ContentPresenter Content="{Binding ResultViewModel}"/>
                    </TabItem>

                    <!--Configuration Tab-->
                    <TabItem Header="Configuration">
                        <ContentPresenter Content="{Binding ConfigViewModel}"/>
                    </TabItem>

                    <!--Others-->
                    <CollectionContainer Collection="{Binding Source={StaticResource Tabs}}"/>
                </CompositeCollection>
            </TabControl.ItemsSource>
        </TabControl>
        <!--#endregion-->    
    </Grid>
    <!--#endregion Main Grid-->
</Window>

If I use the example of the answer linked above is working fine, I can create tabs individually and Result Tab and Configuration Tab, stays the same.

However if I use a UserControl the new TabItem I create out of my Collection put my UserControl inside the TabItem.Header

If I do not follow MVVM and I create a ObservableCollection<TabItem> works as expected, so I assume the problem is on the TabControl.DataTemplate

Any ideas or suggestions would be highly appreciated.

Edit: As I cannot provide a Working example because the complexity of the app and the code involved, I add the following pictures to explain the problem:

Expected View

回答1:

Fixed using ContentTemplateSelector inside TabControl

<Window.Resources>
        <DataTemplate x:Key="DetailedTemplate" DataType="{x:Type viewModels:DetailedViewModel}">
            <views:DetailedView/>
        </DataTemplate>
        <DataTemplate x:Key="ConfigurationTemplate" DataType="{x:Type viewModels:ConfigurationViewModel}">
            <views:ConfigurationView />
        </DataTemplate>
        <DataTemplate x:Key="ResultTemplate" DataType="{x:Type viewModels:ResultViewModel}">
            <views:ResultView/>
        </DataTemplate>

        <helpers:MyViewSelector x:Key="Selector" 
                                DetailedTemplate="{StaticResource DetailedTemplate}" 
                                ConfigurationTemplate="{StaticResource ConfigurationTemplate}"
                                ResultTemplate="{StaticResource ResultTemplate}"/>

</Window.Resources>

Tab Control:

<TabControl Grid.Row="1"
                    Grid.Column="0"
                    VerticalAlignment="Stretch"
                    BorderThickness="0.5"
                    BorderBrush="Black"
                    ContentTemplateSelector="{StaticResource Selector}">
            <TabControl.Resources>
                <CollectionViewSource Source="{Binding Model.DetailsVM}" x:Key="Tabs"/>
                <DataTemplate DataType="{x:Type viewModels:DetailedViewModel}">
                    <TextBlock Text="{Binding Model.SelectedItem.FileInfo.Name, Mode=OneWay}"/>
                </DataTemplate>
            </TabControl.Resources>
            <TabControl.ItemsSource>
                <CompositeCollection>
                    <!--Result View-->
                    <TabItem Header="Import" Content="{Binding ResultViewModel}"/>
                    <!--Configuration Tab-->
                    <TabItem Header="Configuration" Content="{Binding ConfigViewModel}"/>    
                    <!--Others-->
                    <CollectionContainer Collection="{Binding Source={StaticResource Tabs}}"/>
                </CompositeCollection>
            </TabControl.ItemsSource>

</TabControl>

Helper

    public class MyViewSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object inItem, DependencyObject container)
        {
            if (inItem == null)
            {
                return ResultTemplate;
            }

            if (inItem is DetailedViewModel)
            {
                return DetailedTemplate;
            }
            if (inItem is ResultViewModel)
            {
                return ResultTemplate;
            }
            if (inItem is ConfigurationViewModel)
            {
                return ConfigurationTemplate;
            }

            return ResultTemplate;
        }

        public DataTemplate DetailedTemplate { get; set; }
        public DataTemplate ConfigurationTemplate { get; set; }
        public DataTemplate ResultTemplate { get; set; }

    }

Source:

https://stackoverflow.com/a/18312765/2315752

https://jacobaloysious.wordpress.com/2013/08/19/mvvm-using-contenttemplateselector-in-tab-control-view/

https://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplateselector.aspx



标签: c# wpf xaml mvvm