WPF自定义TabControl

12
我需要开发一个自定义的选项卡控件,决定使用 WPF/XAML 进行创建,因为我打算学习它。完成后应该长这样: 目标 我取得了不错的进展,但还有两个问题:
1. 只有第一个/最后一个选项卡应该拥有圆角上/下左边。是否可以修改这些选项卡的样式,类似于我对选中的选项卡所做的方式? 2. 选定的选项卡项目不应在其右侧具有边框。我尝试使用 z-index 和重叠来实现这一点,但结果令人失望。是否有其他方法可以实现这一点? 当前 XAML:
<Window x:Class="MyProject.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="350" Width="500" Margin="5" Background="LightGray">
<Window.Resources>
    <LinearGradientBrush x:Key="SelectedBorderBrush" StartPoint="0,0" EndPoint="1,0">
        <GradientBrush.GradientStops>
            <GradientStopCollection>
                <GradientStop Color="Gray" Offset="0.965"/>
                <GradientStop Color="WhiteSmoke" Offset="1.0"/>
            </GradientStopCollection>
        </GradientBrush.GradientStops>
    </LinearGradientBrush>
    <Style TargetType="{x:Type TabControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabControl}">
                    <DockPanel>
                        <Border
                            Panel.ZIndex="50"
                            Margin="0,100,-1,0" 
                            Background="#FFAAAAAA"
                            BorderBrush="Gray"
                            CornerRadius="7,0,0,7"
                            BorderThickness="1">
                            <TabPanel
                                Margin="0,0,0,0"
                                IsItemsHost="True" />
                        </Border>
                        <Border
                            Background="WhiteSmoke"
                            BorderBrush="Gray"
                            BorderThickness="1"
                            CornerRadius="7,7,7,0" >
                            <ContentPresenter 
                                ContentSource="SelectedContent" />
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type TabItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid>
                        <Border Name="Border" 
                            Background="#FFAAAAAA"
                            CornerRadius="7,0,0,0"
                            BorderBrush="Gray"
                            BorderThickness="0,0,0,1"
                            Panel.ZIndex="50"
                            Margin="0,0,0,0"
                                >

                            <ContentPresenter x:Name="ContentSite"             
                                VerticalAlignment="Center"
                                HorizontalAlignment="Left"
                                ContentSource="Header"
                                Margin="10,10,10,10"/>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Panel.ZIndex" Value="100" />
                            <Setter Property="Margin" Value="0,0,-2,0" />
                            <Setter TargetName="Border" 
                                    Property="BorderBrush" 
                                    Value="{StaticResource SelectedBorderBrush}"/>
                            <Setter TargetName="Border" 
                                Property="Background" 
                                Value="WhiteSmoke" />
                            <Setter TargetName="Border" 
                                Property="CornerRadius" 
                                Value="0,0,0,0" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<Grid>
    <TabControl Name="_menuTabControl" TabStripPlacement="Left" Margin="5">
        <TabItem Name="_tabItem1" Header="First Tab Item" ></TabItem>

        <TabItem Name="_tabItem2" Header="Second Tab Item" >
            <Grid />
        </TabItem>
        <TabItem Name="_tabItem3" Header="Third Tab Item" >
            <Grid />
        </TabItem>
    </TabControl>
</Grid>

编辑:感谢Vlad,我使用渐变边框刷解决了第二个问题。请查看更新后的XAML以获取解决方案。

编辑:Vlad已经解决了第一个问题。

1个回答

9
针对第二个问题,您可以尝试取消裁剪。但请注意可能出现的问题
针对第一个问题,您可以在属性IsSelected上尝试使用样式触发器。(编辑:我看到您正在完全按照这种方式进行操作。)请查看默认模板在MSDN上是如何实现的。请注意,他们也使用了ZIndex编辑:
我找到了解决您的第一个/最后一个选项卡问题的方法。您需要使用附加属性来指定第一个/最后一个选项卡:
在您的TestWindow类中,您定义了附加属性:
public static bool GetIsFirstTab(DependencyObject obj)
{
    return (bool)obj.GetValue(IsFirstTabProperty);
}

public static void SetIsFirstTab(DependencyObject obj, bool value)
{
    obj.SetValue(IsFirstTabProperty, value);
}

public static readonly DependencyProperty IsFirstTabProperty =
        DependencyProperty.RegisterAttached("IsFirstTab", typeof(bool),
               typeof(TestWindow), new UIPropertyMetadata(false));

然后,在您的第一个选项卡中设置此属性:

<Window x:Class="MyProject.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyProject"
        ...
/>
    ...
    <TabItem Name="_tabItem1" Header="First Tab Item"
             local:TestWindow.IsFirstTab="true">
    </TabItem>

然后,您需要为其定义一个触发器:
<Trigger Property="IsSelected" Value="True">
    <Setter TargetName="Border" 
            Property="Background" 
            Value="WhiteSmoke" />
</Trigger>
<Trigger Property="local:Window1.IsFirstTab" Value="True">
    <Setter TargetName="Border" 
            Property="Background" 
            Value="Red" />
</Trigger>

这应该会有所帮助。

对于最后一个选项卡,可以使用相同的技巧。或者您可以将数字作为附加属性,而不是布尔值。


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