【问题标题】:How to style a custom TabItem's Header in a style's trigger?如何在样式触发器中设置自定义 TabItem Header 的样式?
【发布时间】:2015-03-30 09:49:35
【问题描述】:

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>

样式适用于第二个选项卡(具有简单标题),但不适用于第一个选项卡(具有“复杂”标题)。

有没有办法绕过这种行为?我自己想不出一个;我尝试用“TabItem”替换“TextElement”,但没有成功。

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

【问题讨论】:

    标签: wpf xaml triggers tabcontrol controltemplate


    【解决方案1】:

    是的,这是一个难题;继承由逻辑树进行,复杂标头的逻辑父级是 TabItem。如果您在 TabItem 上设置了 Foreground,那么 tabitem 的内容也会继承该前景,这是您不想要的。

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

    【讨论】:

    • 这确实有效,但它显然不能满足我。这是hack-ish。如果我必须在样式中使用实际的 HeaderTemplate 怎么办?
    • 'HeaderTemplate in a style' 是什么意思?但这是真的,如果您作为控制作者无法控制在 Header/Template 中放置的内容,那么这不是最好的解决方案。这里的问题是 TabItem 是复杂标题和复杂内容的逻辑父级。因此,另一种解决方案是在 UI 上的 TabItem 内容中显式设置前景,并在触发器中设置 TabItem 的前景。
    • 是的,这很可能是这里更好的解决方案,除非另有证明......谢谢
    【解决方案2】:

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

    我刚刚在 TabItem 的样式中添加了一个 HeaderTemplate 设置器,并在这里执行我的暗标,绑定到 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>
    

    以及它是如何使用的(将上述样式放置在您的 Window/UserControl/TabControl 的资源中):

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

    由于使用了 StackPanel,如果 SomeValue 为 null,您的 TabItem 将只显示“TabName”。

    【讨论】:

      猜你喜欢
      • 2012-04-05
      • 2019-07-22
      • 1970-01-01
      • 2012-03-26
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      相关资源
      最近更新 更多