选项卡项目和选项卡控件边框样式

20

如何设置选中的标签页没有下划线?

WPF Tab Item

以下是我的标签控件和标签样式。

<!-- Tab control styling -->
        <Style TargetType="{x:Type TabControl}">
            <Setter Property="Padding" Value="10,5,10,5" />
            <Setter Property="Margin" Value="3.5" />
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
        </Style>
        <!-- Tab item styling -->
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border 
                                 Name="Border"
                                 Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
                                 BorderBrush="Black" 
                                 BorderThickness="1,1,1,0" 
                                 CornerRadius="3,3,0,0"
                                 MinWidth="120">
                                    <ContentPresenter x:Name="ContentSite"
                                        VerticalAlignment="Center"
                                        HorizontalAlignment="Center"
                                        ContentSource="Header"
                                        Margin="12,2,12,2"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsFocused" Value="True" >
                                <Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
                                <Setter Property="HeaderTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock FontWeight="Bold" Text="{Binding}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True" >
                                <Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
                                <Setter Property="HeaderTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock FontWeight="Bold" Text="{Binding}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="True" >
                                <Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
                                <Setter Property="HeaderTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBlock FontWeight="Bold" Text="{Binding}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

如果我能够在不过载选项卡项控件模板的情况下实现屏幕截图中显示的外观,则对于我而言没有问题,因为默认的选项卡项模板在所选选项卡上没有底部线。到目前为止,我还没有能够做到这一点。感谢您的帮助。


1
我认为你唯一的选择就是覆盖TabControl模板。 - Martin Moser
感谢您的评论。是的,我可能需要重载TabControl模板。我只是不知道如何绘制TabControl边框的顶部线条,使其具有一条线,但该线在所选TabItem下面不可见。也许TabItem模板可以通过1像素覆盖TabControl,从而允许我通过TabItem模板控制TabItem底部边框线的可见性。目前不确定假设可能实现这一点的XAML会是什么样子。 - dior001
4个回答

24

下面的XAML代码是我如何覆盖TabControl以解决此问题的。关键信息是HeaderPanel的Margin属性。您将看到底部边距为-1,这使其向下移动足够的距离来覆盖该行。

    <Setter Property="Template">
        <Setter.Value>

            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid KeyboardNavigation.TabNavigation="Local">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>

                    <TabPanel x:Name="HeaderPanel"
                              Grid.Row="0"
                              Panel.ZIndex="1"
                              Margin="0,0,4,-1"
                              IsItemsHost="True"
                              KeyboardNavigation.TabIndex="1"
                              Background="Transparent" />

                    <Border x:Name="Border"
                            Grid.Row="1"
                            BorderThickness="1"
                            KeyboardNavigation.TabNavigation="Local"
                            KeyboardNavigation.DirectionalNavigation="Contained"
                            KeyboardNavigation.TabIndex="2">

                        <Border.Background>
                            <SolidColorBrush Color="White"/>
                        </Border.Background>

                        <Border.BorderBrush>
                            <SolidColorBrush Color="White"/>
                        </Border.BorderBrush>

                        <ContentPresenter x:Name="PART_SelectedContentHost"
                                          Margin="4"
                                          ContentSource="SelectedContent" />
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

1
这样做不会隐藏所有的TabItems的底部线,而只会隐藏选定的TabItem的底部线吗? - Rachel
不会,因为当前的TabItem在其他TabHeaders的顶部。它非常流畅。(我已经这样使用了几年)。 - Stewbob
这非常有帮助。在底部边距中分配-1确实解决了问题。谢谢。 - Jerameel Resco
不明白它是如何工作的。我已经给选定的tabItem设置了-1的边距和100的ZIndex,以使其隐藏这条线。 - Maxence
我讨厌这是正确的答案...微软的默认样式与他们应该做的相反。 - claudekennilol
显示剩余2条评论

4

在选项卡控件中添加属性 Padding="0,0,0,0" :-)


2
实际上将其设置为-1会更有效:Padding="-1" - Thinko
我没有看到Padding="0"或Padding="-1"之间的任何区别。 - KarloX

4

不需要修改tabcontrol模板,您可以直接修改TabItem模板,在其上添加两行以覆盖边框,并使用负边距进行覆盖。

(请查看"TopLineCover"和"BottomLineCover"边框。)

enter image description here

<Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
    <Setter Property="Foreground" Value="{DynamicResource VsBrush.WindowText}"/>
    <Setter Property="Background" Value="{DynamicResource VsBrush.Window}"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="HeaderBorder" Padding="8,3,8,3" BorderThickness="1,1,1,0"
                            Background="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBrushKey}}" 
                            BorderBrush="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBorderBrushKey}}">
                        <ContentPresenter x:Name="Content" ContentSource="Header"
                                          HorizontalAlignment="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                          VerticalAlignment="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                          />
                    </Border>
                    <Border x:Name="TopLineCover" BorderThickness="1,1,1,0" Margin="0,-2,0,0" Height="3" Panel.ZIndex="100"
                            Background="{DynamicResource VsBrush.Window}" BorderBrush="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBorderBrushKey}}"
                            VerticalAlignment="Top" HorizontalAlignment="Stretch" Visibility="Collapsed"/>
                    <Border x:Name="BottomLineCover" BorderThickness="0,0,0,3" Margin="1,0,1,-2" Panel.ZIndex="100" BorderBrush="{DynamicResource VsBrush.Window}"
                            VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Visibility="Collapsed"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsSelected" Value="False"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Background" TargetName="HeaderBorder" Value="{DynamicResource VsBrush.Window}"/>
                    </MultiTrigger>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" TargetName="HeaderBorder" Value="{DynamicResource VsBrush.Window}"/>
                        <Setter Property="Visibility" TargetName="TopLineCover" Value="Visible"/>
                        <Setter Property="Visibility" TargetName="BottomLineCover" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

1
过去,我曾通过使TabItem向下延伸一点,以便它实际上绘制在边框元素的顶部并隐藏它来完成此操作。
我记不清我具体是如何做到的,但我认为是通过在TabItem底部使用负边距。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接