2010-04-14 3 views
12

Je dois développer un contrôle de tabulation personnalisé et j'ai décidé de le créer avec WPF/XAML, parce que j'avais prévu de l'apprendre de toute façon. Il devrait ressembler à ceci quand il est fini:WPF Customized TabControl

Target

J'ai fait de bons progrès à ce jour, mais il y a deux questions à gauche:

  1. Seul le premier/dernier élément onglet devrait avoir un arrondi coin supérieur gauche/coin inférieur gauche. Est-il possible de modifier le style de ces éléments, comme je l'ai fait avec l'onglet sélectionné?

  2. L'élément de l'onglet sélectionné ne doit pas comporter de bordure sur son côté droit. J'ai essayé d'accomplir cela avec z-index et chevauchement, mais les résultats ont été plutôt décevants. Y a-t-un autre moyen de faire ça?

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> 

Edit: Merci à Vlad, je pouvais résoudre le deuxième problème avec une brosse frontière gradient. Voir mises à jour XAML pour la solution.

Editer: Vlad corrigé le premier problème.

Répondre

9

Pour le deuxième problème, vous devriez peut-être essayer de remove the clipping? Méfiez-vous cependant du possible issues. Pour le premier problème, vous devez essayer style trigger sur la propriété IsSelected. (Edit: Je vois, vous le faites exactement de cette façon.) Jetez un oeil comment cela est mis en œuvre au modèle par défaut at MSDN. Notez qu'ils utilisent aussi ZIndex.

Modifier:
J'ai trouvé une solution de contournement pour votre premier/dernier problème de l'onglet. Vous devez utiliser les propriétés attachées à désigner le premier/dernier onglet:

Dans votre classe TestWindow vous définissez la propriété ci-joint:

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)); 

Ensuite, dans votre premier onglet vous définissez cette propriété:

<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> 

Ensuite, vous devez définir un déclencheur pour elle:

<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> 

Cela doit aider.

La même astuce fonctionnerait avec le dernier onglet. Ou vous pouvez avoir un nombre au lieu de bool en tant que propriété jointe.

+1

Merci. Tu m'as beaucoup aidé. – xsl

+2

@xsl: vous êtes les bienvenus! – Vlad

+2

VRAIMENT bonne utilisation des accessoires attachés Vlad. Bien joué! – Stimul8d

Questions connexes