none
How to add a "new tab" button to TabControl

    Question

  • How do I add a button instead of an TabItem to a TabControl, similar to the one in internet explorer, add page.
    Thanks!

    volt220
    Friday, December 04, 2009 6:43 PM

Answers

  • Hi,

    still not sure what you're after. If you want to "inject" your own button into the TabControl's header (i.e. where the TabPanel resides in which the tabs are rendered), you can do so by modifying the TabControl's style. Here's a window that is based on the TabControl ControlTemplate sample found in the MSDN docs:

    <Window x:Class="WpfTests.TabControl_ButtonInTabItemPanel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TabControl_ButtonInTabItemPanel" Height="300" Width="300">
    
       <Window.Resources>
          <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
          <SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
          <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
          <SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
    
          <Style  TargetType="{x:Type TabControl}">
             <Setter Property="OverridesDefaultStyle" Value="True" />
             <Setter Property="SnapsToDevicePixels" Value="True" />
             <Setter Property="Template">
                <Setter.Value>
                   <ControlTemplate TargetType="{x:Type TabControl}">
                      <Grid KeyboardNavigation.TabNavigation="Local">
                         <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                         </Grid.RowDefinitions>
                         <!-- This inserts the button -> -->
                         <Grid>
                            <Grid.ColumnDefinitions>
                               <ColumnDefinition Width="Auto"/>
                               <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Button x:Name="TabPanelButton"                            
                                    Command="{Binding TabPanelButtonClickCommand}"
                                    Margin="0,0,15,0" 
                                    Content="A TabPanelButton" 
                                    Height="20"/>
                            <TabPanel Name="HeaderPanel"
                                      Grid.Column="1"
                                      Panel.ZIndex="1" 
                                      Margin="0,0,4,-1" 
                                      IsItemsHost="True"
                                      KeyboardNavigation.TabIndex="1"
                                      Background="Transparent" />
                         </Grid>
                         <!-- <- This inserts the button -->
                         <Border Name="Border" 
                                    Grid.Row="1" 
                                    Background="{StaticResource WindowBackgroundBrush}" 
                                    BorderBrush="{StaticResource SolidBorderBrush}" 
                                    BorderThickness="1" 
                                    CornerRadius="2" 
                                    KeyboardNavigation.TabNavigation="Local"
                                    KeyboardNavigation.DirectionalNavigation="Contained"
                                    KeyboardNavigation.TabIndex="2" >
                            <ContentPresenter Name="PART_SelectedContentHost"
                                                 Margin="4"
                                                 ContentSource="SelectedContent" />
                         </Border>
                      </Grid>
                      <ControlTemplate.Triggers>
                         <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
                            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
                         </Trigger>
                      </ControlTemplate.Triggers>
                   </ControlTemplate>
                </Setter.Value>
             </Setter>
          </Style>
       </Window.Resources>
       
       <TabControl x:Name="tc" Margin="5">
          <TabItem Header="Tab 1"/>
          <TabItem Header="Tab 2"/>
          <TabItem Header="Tab 3"/>
       </TabControl>
    </Window>
    

    Code-behind:

    using System.Windows;
    using System.Windows.Input;
    using System;
    
    namespace WpfTests
    {
       public partial class TabControl_ButtonInTabItemPanel : Window
       {
          //This will route a click on the button to the ButtonCommand-class (see XAML). 
          public static ICommand TabPanelButtonClickCommand { get { return new ButtonCommand(); } }
    
          public TabControl_ButtonInTabItemPanel()
          {
             InitializeComponent();
             //We need to set the DataContext of the window for this to work.
             this.DataContext = this;
          }
       }
    
       public class ButtonCommand : ICommand
       {
          //You could place your own logic here that would enable or disable the
          //button by returning true/false.
          public Boolean CanExecute(Object parameter)
          {
             return true;
          }
    
          public event EventHandler CanExecuteChanged
          {
             add { CommandManager.RequerySuggested += value; }
             remove { CommandManager.RequerySuggested -= value; }
          } 
    
          //This gets fired when the command is executed (i.e. the button has been clicked).
          public void Execute(Object parameter)
          {
             MessageBox.Show("You clicked the button.");
          } 
       }
    }
    

    As you can see, while inserting a button into the header-area is actually just a matter of modifying the style, reacting to a click on it requires more work. For more information on this, see the MDSN on RoutedCommands .

    If this still isn't what you're after, try to be more specific - "something similar" doesn't really help describe your problem.

    Cheers,
    Olaf
    • Marked as answer by volt220 Monday, December 07, 2009 9:08 AM
    Saturday, December 05, 2009 12:07 PM

All replies

  • It's not all too clear exactly what you're after - have you seen this CodeProject article ?
    Cheers,
    Olaf
    Friday, December 04, 2009 7:42 PM
  • Thanks Olaf, Yes I have seen that project, it seem a bit complicated for a newbie :)
    I was looking for a simple way, maybe it is simple and I have to give it another shoot.


    I was looking for something similar:
    <TabControl x:Name="tabControl">
          <Button Click="newTab_Click">Add tab</Button>
          <TabItem Header="Tab1"></TabItem>
    </TabControl>
    In this case I don't wan't a new tabItem for the <button>, but something similiar to that
    project you refer to, "NewTabButtonStyle"

    WPF vs me -> Round 1 to WPF
    volt220
    Friday, December 04, 2009 9:10 PM
  • Hi,

    still not sure what you're after. If you want to "inject" your own button into the TabControl's header (i.e. where the TabPanel resides in which the tabs are rendered), you can do so by modifying the TabControl's style. Here's a window that is based on the TabControl ControlTemplate sample found in the MSDN docs:

    <Window x:Class="WpfTests.TabControl_ButtonInTabItemPanel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TabControl_ButtonInTabItemPanel" Height="300" Width="300">
    
       <Window.Resources>
          <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
          <SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
          <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
          <SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
    
          <Style  TargetType="{x:Type TabControl}">
             <Setter Property="OverridesDefaultStyle" Value="True" />
             <Setter Property="SnapsToDevicePixels" Value="True" />
             <Setter Property="Template">
                <Setter.Value>
                   <ControlTemplate TargetType="{x:Type TabControl}">
                      <Grid KeyboardNavigation.TabNavigation="Local">
                         <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                         </Grid.RowDefinitions>
                         <!-- This inserts the button -> -->
                         <Grid>
                            <Grid.ColumnDefinitions>
                               <ColumnDefinition Width="Auto"/>
                               <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Button x:Name="TabPanelButton"                            
                                    Command="{Binding TabPanelButtonClickCommand}"
                                    Margin="0,0,15,0" 
                                    Content="A TabPanelButton" 
                                    Height="20"/>
                            <TabPanel Name="HeaderPanel"
                                      Grid.Column="1"
                                      Panel.ZIndex="1" 
                                      Margin="0,0,4,-1" 
                                      IsItemsHost="True"
                                      KeyboardNavigation.TabIndex="1"
                                      Background="Transparent" />
                         </Grid>
                         <!-- <- This inserts the button -->
                         <Border Name="Border" 
                                    Grid.Row="1" 
                                    Background="{StaticResource WindowBackgroundBrush}" 
                                    BorderBrush="{StaticResource SolidBorderBrush}" 
                                    BorderThickness="1" 
                                    CornerRadius="2" 
                                    KeyboardNavigation.TabNavigation="Local"
                                    KeyboardNavigation.DirectionalNavigation="Contained"
                                    KeyboardNavigation.TabIndex="2" >
                            <ContentPresenter Name="PART_SelectedContentHost"
                                                 Margin="4"
                                                 ContentSource="SelectedContent" />
                         </Border>
                      </Grid>
                      <ControlTemplate.Triggers>
                         <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
                            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
                         </Trigger>
                      </ControlTemplate.Triggers>
                   </ControlTemplate>
                </Setter.Value>
             </Setter>
          </Style>
       </Window.Resources>
       
       <TabControl x:Name="tc" Margin="5">
          <TabItem Header="Tab 1"/>
          <TabItem Header="Tab 2"/>
          <TabItem Header="Tab 3"/>
       </TabControl>
    </Window>
    

    Code-behind:

    using System.Windows;
    using System.Windows.Input;
    using System;
    
    namespace WpfTests
    {
       public partial class TabControl_ButtonInTabItemPanel : Window
       {
          //This will route a click on the button to the ButtonCommand-class (see XAML). 
          public static ICommand TabPanelButtonClickCommand { get { return new ButtonCommand(); } }
    
          public TabControl_ButtonInTabItemPanel()
          {
             InitializeComponent();
             //We need to set the DataContext of the window for this to work.
             this.DataContext = this;
          }
       }
    
       public class ButtonCommand : ICommand
       {
          //You could place your own logic here that would enable or disable the
          //button by returning true/false.
          public Boolean CanExecute(Object parameter)
          {
             return true;
          }
    
          public event EventHandler CanExecuteChanged
          {
             add { CommandManager.RequerySuggested += value; }
             remove { CommandManager.RequerySuggested -= value; }
          } 
    
          //This gets fired when the command is executed (i.e. the button has been clicked).
          public void Execute(Object parameter)
          {
             MessageBox.Show("You clicked the button.");
          } 
       }
    }
    

    As you can see, while inserting a button into the header-area is actually just a matter of modifying the style, reacting to a click on it requires more work. For more information on this, see the MDSN on RoutedCommands .

    If this still isn't what you're after, try to be more specific - "something similar" doesn't really help describe your problem.

    Cheers,
    Olaf
    • Marked as answer by volt220 Monday, December 07, 2009 9:08 AM
    Saturday, December 05, 2009 12:07 PM