Version

Removing a Closed Tab

Before You Begin

When an end user closes a tab, xamTabControl™ does not remove the tab from the Items collection; it hides it instead. In cases where the tab contains resource-heavy objects, you may want to remove the tab from the Items collection so the garbage collector can reclaim the resources. If you are using individual tabs to represent an entity instance from your data model (e.g., a Customer, an Order, etc) and you are treating each tab similar to a Form, removing each tab from the Items collection as each tab is closed will ensure the smallest memory and resource footprint for your application.

One thing you have to be aware of when defining tabs in XAML is the Name property. If you do not name the tabs in XAML, you can simply remove the tab from xamTabControl’s Items collection. However, if you name a tab in XAML, you have to take two additional steps after you remove the tab from the Items collection. You must unregister the tab’s name from the Window’s namescope and set all references to the TabItemEx object, including the Window’s instance variable, to null.

What You Will Accomplish

You will handle the TabItemEx object’s Closed event and remove the TabItemEx object from xamTabControl’s Items collection.

Follow these Steps

  1. Add an instance of xamTabControl to your Window.

    1. Set the Name property so you can reference it from the code-behind.

    2. Set the AllowTabClosing property to True.

    3. Attach an event handler to the TabItemEx object’s Closed event.

Since the TabItemEx object’s Closed event is a routed event that bubbles up, you can attach an event handler on the xamTabControl instead of on each individual instance of the TabItemEx class.

In XAML:

<igWindows:XamTabControl
    Name="xamTabControl1"
    AllowTabClosing="True"
    igWindows:TabItemEx.Closed="OnTabClosed">
    <!--TODO: Add TabItemEx objects here-->
</igWindows:XamTabControl>
  1. Add a TabItemEx object to xamTabControl.

    1. Set the Name property to "tab1".

    2. Set the Header property to "Tab 1".

In XAML:

<igWindows:TabItemEx Header="Tab 1" Name="tab1">
    <!--TODO: Add a panel here-->
</igWindows:TabItemEx>
  1. Add a second TabItemEx object to xamTabControl and set its Header property to "Tab 2".

In XAML:

<igWindows:TabItemEx Header="Tab 2">
    <!--TODO: Add a panel here-->
</igWindows:TabItemEx>
  1. Open the code-behind and add using/Imports directives so you don’t need to type out a member’s fully qualified name.

In Visual Basic:

Imports Infragistics.Windows.Controls

In C#:

using Infragistics.Windows.Controls;
  1. Add an event handler for the TabItemEx object’s Closed event.

In Visual Basic:

Private Sub OnTabClosed(sender As Object, e As RoutedEventArgs)
    'TODO: Add code to remove tabs here
End Sub

In C#:

private void OnTabClosed(object sender, RoutedEventArgs e)
{
    //TODO: Add code to remove tabs here
}
  1. Remove the TabItemEx object from xamTabControl’s Items collection.

Note
Note

If you did not name any TabItemEx objects in XAML, you do not have to implement steps seven and on.

In Visual Basic:

Me.xamTabControl1.Items.Remove(e.Source)

In C#:

this.xamTabControl1.Items.Remove(e.Source);
  1. Cast the RoutedEventArg object’s Source property to a TabItemEx object.

When you name an element in XAML, it causes several things to happen which allow you to reference the element from the code-behind. This "magic" keeps the objects alive even when you remove them from the visual tree or logical tree at run time.

In Visual Basic:

Dim tab As TabItemEx = DirectCast(e.OriginalSource, TabItemEx)

In C#:

TabItemEx tab = (TabItemEx)e.OriginalSource;
  1. Make sure that the TabItemEx object’s Name property is not an empty string or null.

In Visual Basic:

If Not String.IsNullOrEmpty(tab.Name) Then
    'TODO: Unregister the tab's name
    'TODO: Set the instance variable for the TabItemEx object to null
End If

In C#:

if(!string.IsNullOrEmpty(tab.Name))
{
    //TODO: Unregister the tab's name
    //TODO: Set the instance variable for the TabItemEx object to null
}
  1. Unregister the tab’s name from the Window’s namescope.

In order to keep this walkthrough as simple as possible, the example code does not use any try/catch blocks or conditional statements to verify the existence of the name in the namescope.

In Visual Basic:

Me.UnregisterName(tab.Name)

In C#:

this.UnregisterName(tab.Name);
  1. Create a switch statement based on the TabItemEx object’s Name property.

In Visual Basic:

Select Case tab.Name
    'TODO:  Add Case statements here
End Select

In C#:

switch(tab.Name)
{
    //TODO: Add Case statements here
}
  1. Add Case statements for any name that you declared in XAML.

In Visual Basic:

Case "tab1"
    'TODO: Set the instance variable that corresponds to the tab's name to Nothing
    Exit Select

In C#:

case "tab1":
    //TODO: Set the instance variable that corresponds to the tab's name to null
    break;
  1. In each Case statement, set the instance variable that corresponds to the tab’s name to null.

If there are any other instance variables in your Window that reference the tab, you must also set those to null.

In Visual Basic:

tab1 = Nothing

In C#:

tab1 = null;
  1. Run the project.

You can close the tabs by middle clicking a tab’s header. From the end user’s perspective, the tab closing behavior does not change. However, if your tabs contain resource heavy objects, the end user’s experience will be better as the tabs are garbage collected when they are closed.