Click here to Skip to main content
Click here to Skip to main content

An Extended WPF TabControl

By , 5 Apr 2009
 
Screenshot - TabControl_Default.jpg

Introduction

I recently decided to have a go at changing the built-in WPF TabControl so that it behaves similar to the way in which Internet Explorer 7 works.

The main area I wanted to change was the way in which the TabItems are arranged, currently the built-in TabControl will pack and stack items, so the more items there are, the more room is required for the headers, taking up space from the actual content of the TabItem.

With Internet Explorer 7, tabs remain on a single row and will scroll in and out of view. This is the way I wanted this control to behave.

Properties/Events

There are a few extra properties (Dependency Properties) and events added to the control.

  • AllowAddNew - Setting this property to true will allow the end user to add new tabitems to the control via a button.
  • AllowDelete - Setting this property to true will allow the end user to delete tabitems from the control by clicking on the close button on the selected tabitem.

If the above properties are set to true, there are three events that go with these properties. They are TabItemAdded, TabItemClosing and TabItemClosed: all provide a reference to the TabItem being added/removed, the TabItemClosing event providing a place to cancel the close if required.

  • AddNewTabToEnd - If this property is true, tabitems added using the AddNew button will be added to the end of the row of tabitems, otherwise the new tabitem will be inserted immediately after the current selection.
  • SelectNewTabOnCreate - If this property is true, focus will be moved to the new tabitem when added.

Finally, there are three extra properties of type Brush which are used for coloring the tabitems based on their state:

  • TabItemNormalBackground
  • TabItemMouseOverBackground
  • TabItemSelectedBackground

If you look at the picture at the top of this article, it shows the default style for the TabControl. I've intentionally made this very basic. By just using the extra Background properties, you can easily change the appearance of the TabControl. As this picture shows, by adding a few LinearGradientBrushes, you can get something that resembles Internet Explorer 7.

TabControl_IE7.jpg

There are four properties which take an active part in the arrangement of the tabitems. They are:

  • TabItemMinWidth
  • TabItemMaxWidth
  • TabItemMinHeight
  • TabItemMaxHeight

Arranging the TabItems

There are three ways in which the tabcontrol arranges its tabitems.
The following description is relevant if the TabStripPlacement property is set to Top or Bottom.

  1. If the combined widths of the TabItems is less than the available visible space, then we just arrange them one after the other, taking into account the TabItemMaxWidth and TabItemMinWidth properties.
  2. If the combined widths are greater than visible, then calculate the width required for all the tabitems so that all are visible. If this width is greater than the TabItemMinWidth property, then we arrange the tabitems using this calculated width.
  3. Once we add too many tabitems that their widths would be less than the TabitemMinWidth property, then scrolling will be enabled.

The class that is responsible for arranging the tabitems is the VirtualizingTabPanel. As the name suggests, this panel derives from the VirtualizingPanel class and implements the IScrollInfo interface. I won't describe here what a VirtualizingPanel is, instead I will just direct you to this Blog post by Dan Crevier which describes what it is and how to implement one.

Using the Code

To use the control, you will need to add a reference to the Wpf.TabControl assembly, then add an xmlns to the window:

xmlns:r="clr-namespace:Wpf.Controls;assembly=Wpf.TabControl" 

The demo provided shows how to add the control to a window and set its properties.

History

  • 13-Oct-2007: Initial upload
  • 09-Mar-2009: Implemented ItemsSource binding & bug fixes
  • 05-Apr-2009: Updated source code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

alrh
Software Developer
United Kingdom United Kingdom
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow can I integrate this into the Prism technology?memberVcDeveloper128-May-13 15:38 
Hi, this a very nice extension to the TabControl and I need it from my project. But, I need help trying to figure out how to use it with the Prism technology when a View.xaml is added to a TabControl.
 
Will not be using the add button, so I need some kind a event that will trigger the AddTabItem(). Any suggestions?
GeneralMy vote of 4membervanwood26-Feb-13 2:05 
Nice control!
GeneralMy vote of 5memberhari111r28-Nov-12 17:55 
Great. Thanks for sharing.
QuestionFirst Tab isfixedmemberPatrick Blackman20-Jun-12 17:14 
Is there a way to have the first tab as fixed (not taking part in the scrolling) and just scroll all the other tabs.
QuestionHow I can use this Tab control in WinApp projects?memberctrlz-jc13-May-12 18:19 
Your Tab Control is Amazing! I really need to it.
Please help me, thanks.
GeneralMy vote of 5 [modified]memberSteve Aube 126-Dec-11 11:24 
Exactly what I was looking for. Thanks for contributing this article.

modified 26-Dec-11 18:06pm.

GeneralMy vote of 5memberKashif_Imran11-Dec-11 0:31 
Helped me a lot.
GeneralMy vote id 5memberedallos22-Mar-11 0:46 
Excelent work. Thank you for your publishing.
GeneralMy vote of 5memberSlacker0078-Dec-10 7:24 
Thanks for sharing. Good job.
GeneralModifying tab control to show the selected tabs header in bold [modified]memberACanadian17-Sep-10 9:24 
Hi,
 
Your control is great Smile | :)
 
Though I am having trouble modifying the tab control that uses ItemProperties to update after modifying the Generic.xaml file. I've adjusted the file to make the text in the header of the selected tab bold. This change correctly affects tab control that uses Items Source Property.
 
My change was simple... just included the following code into the appropriate IsSelected trigger.
 
<Setter Property="TextElement.FontWeight" TargetName="Bd" Value="Bold"/>
 
Any thoughts on the subject would be greatly appreciated.
 
Tim

modified on Friday, September 17, 2010 4:35 PM

GeneralMy vote of 4memberSteven Chen11-Aug-10 6:03 
Great
GeneralMy vote of 5memberzokbari2-Aug-10 7:46 
Excellent work! vote 5.
QuestionWhat controls the default xaml when first dropped onto designer?memberpatc23-Jun-10 16:53 
Where does that initial xaml come from?
 
What if I wanted the default tabcontrol dropped onto the designer to have two tabs?
GeneralProperties TabItemNormalBackground, TabItemMouseOverBackground, TabItemSelectedBackground for each TabItemmemberjiglriv9-May-10 23:42 
Hello, I'm trying to put these properties for each TabItem. anyone know how they can do?
GeneralIsFixedSize property questionmemberMember 45553309-May-10 4:22 
Thank you for a great control!
I'm sorry, if my question looks stupid)
I've tried to bind ItemsSource to a IList<my_class> and got the IsFixedSize == true.
Can you explain me how that works:
private bool IsFixedSize
        {
            get
            {
                IEnumerable items = GetItems();
                return items as IList == null || (items as IList).IsFixedSize;
            }
        }
Thank you!)
QuestionThank you and a questionmembermsabatini28-Apr-10 6:29 
Hi, first of all many thanks and congratulations to the author for this control; next my question is:
I need to modify the TabStripPlacement Top template by moving the PART_NewTabButton from the 2nd column to the right of the currently selected tab (kind of IE, Firefox, Chrome), so I only made this modifications:
 
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>
 
and changed the Grid.Column indexing, like this:
 
  <Button 
    x:Name="PART_NewTabButton" 
    Grid.Column="3" 
    Height="22"
    VerticalAlignment="Bottom"
    Margin="-1,5,0,-1" 
    KeyboardNavigation.TabIndex="2"
    Style="{StaticResource NewTabButtonStyle}" 
    Width="24"
    Visibility="{Binding Path=AllowAddNew, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource boolConverter}}"
    ToolTip="Add a New tab">
    <Image Source="pack://application:,,,/Wpf.TabControl;component/Images/newtab.ico"/>
  </Button>
 
and similarly for the other components in the grid.
 
My result is that the PART_NewTabButton is aligned to the extreme right in the grid, leaving empty space between the selected tab and the PART_NewTabButton, and no change in the Width values for Grid.ColumnDefinitions gave me the desired positioning (for example, setting all "Auto" made the RepeatButtons not working).
Does anybody have any suggestion?
QuestionWhat a good articlemembersuperdiablo18-Apr-10 6:17 
Thanks a lot to the author!
GeneralThank you and new functionality implementedmemberEvgeny Vinnik2-Jul-09 18:09 
Hello,
Thank you for this great article.
 
I've added drag-and-drop functionality using code from article Implementing Drag/Drop with TabControl
Also I added context menu with commands like "close all but me", "close me", "new tab" (just like in Internet Explorer)
 
I think we could make an update.
GeneralRe: Thank you and new functionality implementedmemberJose Maldonado5-Jan-10 5:38 
please, share it, with this contribution would be very very excellent control!
GeneralRe: Thank you and new functionality implementedmemberMember 155142618-Nov-10 3:30 
Hello!
 
I'm interested how you have implemented "close me"...
Thank you very much!
 
Roberto
GeneralBug: RepeatRight and RepeatLeft buttons do not display in WindowUsingItemsSourceProperty.xamlmemberRolenun24-May-09 18:27 
This issue is shown when enough tabs are added to exceed the width of the window.
 
To correct this problem, add: TabItemMinWidth="150" to line 35 of WindowUsingItemsSourceProperty.xaml as follows:
 
<r:TabControl Margin="10" x:Name="tabControl" TabStripPlacement="{Binding ElementName=listBox, Path=SelectedItem}" TabItemMinWidth="150" TabItemMaxWidth="300" TabItemMinHeight="30" TabItemMaxHeight="50" VerticalContentAlignment="Center" ItemsSource="{Binding DynamicObjects, ElementName=root}">
General[My vote of 2] need code snippets and discussionmemberDonsw16-Apr-09 6:44 
you need code snippets and discussion to have a good article. you can do better. Frown | :(
 
cheers,
Donsw
My Recent Article : Ajax Calendar Control

GeneralRe: [My vote of 2] need code snippets and discussionmvpJohn Simmons / outlaw programmer17-Jun-11 2:15 
I compensated the 1-vote your comment received with a 5. I agree with your opinion.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
-----
You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
-----
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997

GeneralMy vote of 2mvpJohn Simmons / outlaw programmer15-Apr-09 2:53 
No discussion of the code, and no code snippets. This is barely an article.
GeneralRe: My vote of 2memberr2d2ro17-Jun-11 0:12 
I think you are wrong. The article is explaining the functionality of the control very well(and I am a rookie developer, so if it was easy to me...). The code contains useful comments and is very clear and well organized.
I am sure lots of developers found here a perfect solution for a flexible tab control.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 5 Apr 2009
Article Copyright 2007 by alrh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid