Question

I have a TabControl item in WPF .Net with 2 templates for content and 2 templates for tabitems. I bind my own objects as ItemsSource, which has two properties:

public bool IsPrivMsgChannel
{
    get
    {
        return _IsPrivMsgChannel;
    }
    set
    {
        _IsPrivMsgChannel = value;
        if (_IsPrivMsgChannel)
        {
            Joined = true;
        }
    }
}

And

public bool Joined
{ 
    get
    {
        return _Joined;
    }
    set
    {
        _Joined = value;
        // Notify the UI thread!
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("Joined"));
    }
}

The first property will be set when the object is initialized, it won't change. The second property may change, and it sends a notification then to the UI.

I would like to change the TabItem template of my TabContol based on the IsPrivMsgChannel property, and the TabContent template based on the Joined property.


UPDATE My solution is looks like this right now:

<TabControl x:Name="Channels" Grid.Column="0" Grid.Row="1" TabStripPlacement="Left" SelectionChanged="ChannelChanged" ContentTemplateSelector="{StaticResource MyContentTemplateSelector}" ItemTemplateSelector="{StaticResource MyItemTemplateSelector}">
<TabControl.Resources>
    <DataTemplate x:Key="TabItemChannelTemplate">
        <Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Name}"></Label>
    </DataTemplate>
    <DataTemplate x:Key="TabItemPrivChatTemplate">
        <Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="Private"></Label>
    </DataTemplate>

    <DataTemplate x:Key="TabContentDisconnected">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>

            <Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Description}"></Label>
            <Button Grid.Column="0" Grid.Row="1" Width="100" Content="Enter this channel" Click="Enter_Channel"></Button>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="TabContentConnected">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>

            <Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Description}"></Label>
            <Button Grid.Column="0" Grid.Row="1" Width="100" Content="Leave this channel" Click="Leave_Channel"></Button>
            <DockPanel Grid.Column="0" Grid.Row="2">
                <ListBox x:Name="GameList" HorizontalContentAlignment="Stretch" ItemTemplate="{DynamicResource GameListTemplate}" ItemsSource="{Binding GameList}" Visibility="{Binding CanHost, Converter={StaticResource BoolToVisibilityConverter}}" DockPanel.Dock="Top" Height="250" SelectionChanged="GameListSelectionChanged"></ListBox>
                <ScrollViewer VerticalScrollBarVisibility="Auto" ScrollChanged="MessageScrollChanged" DockPanel.Dock="Bottom">
                    <TextBox x:Name="Messages" Text="{Binding Messages}" TextWrapping="Wrap"></TextBox>
                </ScrollViewer>
            </DockPanel>
        </Grid>
    </DataTemplate>
    <Style TargetType="{x:Type TabItem}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Joined}" Value="True">
                <Setter Property="ContentTemplate" Value="{StaticResource TabContentConnected}"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</TabControl.Resources>
</TabControl>

So I made two DataTemplateSelector class. One will select the template for the Items and one will select the template for the Content.

But since Joined property can change I must create Style.Triggers to handle if that property changes and change the ContentTemplate if needed.

The only thing I can't understand is why triggers work only with TargetType TabItem of the Style and not with TargetType TabControl.

Was it helpful?

Solution

Sounds to me like you want to use a DataTemplateSelector. There's an example of using it here: http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector

Basically, you implement a DataTemplateSelector where the SelectTemplate method selects which template to use based on the container and the item, create an instance of it in your XAML then assign it to a ItemTemplateSelector attribute on an items control.

OTHER TIPS

Modify the Data Triggers as given below.

   <DataTrigger Binding="{Binding Path=DataContext.Joined,RelativeSource={RelativeSource Self}}" Value="True">
     <Setter Property="ContentTemplate" Value="{DynamicResource TabContentConnected}" />
   </DataTrigger>
   <DataTrigger Binding="{Binding Path=DataContext.IsPrivMsgChannel,RelativeSource={RelativeSource Self}}" Value="True">
     <Setter Property="ItemTemplate" Value="{DynamicResource TabItemTemplate2}" />
   </DataTrigger>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top