如何在样式的触发器中设置自定义TabItem的标题样式?

时间:2015-03-30 09:49:35

标签: wpf xaml triggers tabcontrol controltemplate

关注my first question后,我留下了以下XAML:

<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl>
            <TabControl.Resources>
                <Style TargetType="{x:Type TabItem}">
                    <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type TabItem}">
                                <Border BorderBrush="Transparent" Background="Transparent">
                                        <ContentPresenter x:Name="TabItemContent" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>                                    
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter Property="TextElement.Foreground" Value="DarkOrange" TargetName="TabItemContent"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>    
                </Style>
            </TabControl.Resources>
            <TabItem>
              <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                  <TextBlock Text="First"/>
                  <TextBlock Text="Tab"/>
                </StackPanel>
              </TabItem.Header>
              <TextBlock Text="TextBlock"/>                    
            </TabItem>
            <TabItem Header="TAB2">
               <TextBlock Text="TextBlock too"/>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

样式适用于第二个标签(有一个简单的标题),但不适用于第一个标签(带有复杂的标题)。

有没有办法绕过这种行为?我自己也想不到一个;我尝试更换&#34; TextElement&#34;通过&#34; TabItem&#34;没有成功。

编辑:删除了不相关的XAML部分。

2 个答案:

答案 0 :(得分:1)

是的,这是一个难题;继承由逻辑树工作,复杂头的逻辑父是TabItem。如果在TabItem上设置Foreground,则tabitem的内容也将继承该前景,这是您不想要的。

幸运的是,有一个简单的解决方案:将UI放在HeaderTemplate而不是Header属性中。模板的根目录没有逻辑父项,但它确实将ContentPresenter作为其TemplatedParent,显然继承也从模板化父项传播到模板中的根。

答案 1 :(得分:1)

所以我想出了一个有点优雅的解决方案,尽管非常有限(只有你的自定义标题只包含2个文本元素才能使用,如果你想要更多,那么这不会起作用,虽然用图像替换TextBlock似乎不可能;但是,2个元素。)

我刚刚在TabItem的样式中添加了一个HeaderTemplate setter,并在此处执行黑暗出价,绑定到Tag以获取该标签的名称。

这是怎么回事:

<Style TargetType="{x:Type TabItem}">
    <Setter Property="HeaderTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=TabItem}}" Margin="2,0"/>
                    <TextBlock Text="{Binding}" Margin="2,0"/>
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <ContentPresenter x:Name="TabItemContent" ContentSource="Header" HorizontalAlignment="Center" Margin="4" RecognizesAccessKey="True"/>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="TabItemContent" Property="TextElement.Foreground" Value="DarkOrange"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

以及它是如何使用的(将上面的Style放在你的Window / UserControl / TabControl资源中):

<TabItem Header="{Binding SomeValue}" Tag="TabName">
    <some:Controls/>
</TabItem>

由于使用了StackPanel,如果SomeValue为null,则TabItem将仅显示&#34; TabName&#34;。