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