2010-04-14 99 views
12

我必须开发一个自定义的选项卡控件,并决定使用WPF/XAML创建它,因为无论如何我都打算学习它。它应该是这样的,当它完成:WPF自定义TabControl

Target

我取得了良好进展,到目前为止,但有两个问题留给:

  1. 只有第一个/最后一个选项卡项目应该有一个圆左上角/左下角。是否可以修改这些项目的样式,类似于我对选定选项卡项目的方式?

  2. 所选标签项目的右侧不应有边框。我试图用z-index和重叠来实现这一点,但结果相当令人失望。有没有其他方法可以做到这一点?

Current

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> 

编辑:感谢弗拉德,我能解决的渐变边框刷第二个问题。查看该解决方案的更新XAML。

编辑:弗拉德修复了第一个问题。

回答

9

对于第二个问题,您应该尝试remove the clipping?但请注意possible issues

对于第一个问题,您应该在属性IsSelected上尝试style trigger。 (编辑:我明白了,你正是这样做的。)看看这是如何在默认模板at 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> 

这一定帮助。

相同的技巧将与最后一个标签一起使用。或者你可以有一个数字而不是bool作为附加属性。

+1

谢谢。你帮了我很多。 – xsl 2010-04-14 11:02:39

+2

@xsl:不客气! – Vlad 2010-04-14 11:28:21

+2

真的很好用附加道具弗拉德。确实做得好! – Stimul8d 2010-09-21 11:17:33