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.