DataTemplateSelector in WPF

Mrg Gek picture Mrg Gek · Aug 13, 2015 · Viewed 7.2k times · Source

I want to switch between two views that have different bindings and controls. Can I do this using DataTemplateSelector?

<TabControl
        ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedTabIndex, Mode=TwoWay}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <TextBlock Text="{Binding TabName}"><TextBlock.Background><SolidColorBrush /></TextBlock.Background></TextBlock>
                    <Button Name="btnDelete" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="0"  CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}" BorderBrush="#00000000">
                        <Image Source="/WPF_AccApp;component/Images/11.gif" Height="11" Width="11"></Image>
                    </Button>
                    <DockPanel.Background>
                        <SolidColorBrush />
                    </DockPanel.Background>
                </DockPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
                <DataTemplate>
                        <y:TabView /> //Here I want to have two diferent views
                    </DataTemplate>
            </TabControl>

Answer

Dennis picture Dennis · Aug 13, 2015

Actually, it depends on switching logic and how view models are designed. There can be more than one solution. E.g., here's sample without DataTemplateSelector at all, it is based on style trigger.

View model:

public class ItemVm
{
    public string Name { get; set; }
    public bool IsSelected { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
}

XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!-- This one chooses the view -->
    <CheckBox x:Name="ViewSelector" Content="View shapes"/>

    <TabControl Grid.Row="1" ItemsSource="{Binding}">
        <TabControl.Resources>
            <DataTemplate x:Key="TextualTemplateKey">
                <StackPanel>
                    <TextBlock Text="{Binding X}"/>
                    <TextBlock Text="{Binding Y}"/>
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="ShapesTemplateKey">
                <Rectangle Fill="Green" Width="{Binding X}" Height="{Binding Y}"/>
            </DataTemplate>
        </TabControl.Resources>
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                <Setter Property="ContentTemplate" Value="{StaticResource TextualTemplateKey}"/>
                <Style.Triggers>
                    <!-- When "View shapes" is checked, we're changing data template to a new one -->
                    <DataTrigger Binding="{Binding IsChecked, ElementName=ViewSelector}" Value="True">
                        <Setter Property="ContentTemplate" Value="{StaticResource ShapesTemplateKey}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</Grid>

DataTemplateSelector allows you to implement more sophisticated logic, but also has its own cons: if you want to get something from the view, you have to walk through the elements tree.