2

I have a TabControl where the TabItems are DataTemplated. The template seems to work correctly, in that the usercontrol I want to show in the TabItem is showing correctly.

What I am not sure of is how to get a "x" to show up in the TabItem so I can close each tab, since they are dynamically generated through a template.

Being fairly new to WPF, I am starting to pick up on many of the concepts, but the TabControl gave me a lot of trouble, so I may very well have the template workable, but not maintainable.

This is what I have, and I would like to be able to close each TabControl. I will also need to be able to fire a custom event when that TabControl is closed.

<UserControl x:Class="Russound.Windows.UI.UserControls.CallLog.CaseReaderWpf"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:CallLog="clr-namespace:Russound.Windows.UI.UserControls.CallLog"
    Height="637" Width="505">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Russound.Windows;component/UI/RussoundDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <TabControl x:Name="tabCases" >
        <TabControl.ItemTemplate>
            <DataTemplate DataType="{x:Type TabItem}">
                <StackPanel>
                    <TextBlock Text="{Binding Path=Id}" />
                </StackPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate DataType="{x:Type TabItem}">
                <CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</UserControl>
Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Russ
  • 12,312
  • 20
  • 59
  • 78

5 Answers5

7

Check out this MSDN article by Josh Smith. It is an excellent solution for your question.

WPF Apps With The Model-View-ViewModel Design Pattern

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

<!-- 
This template explains how to render 
a tab item with a close button.
-->
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel Width="120">
  <Button 
    Command="{Binding Path=CloseCommand}"
    Content="X"
    Cursor="Hand"
    DockPanel.Dock="Right"
    Focusable="False"
    FontFamily="Courier" 
    FontSize="9"
    FontWeight="Bold"  
    Margin="0,1,0,0"
    Padding="0"
    VerticalContentAlignment="Bottom"
    Width="16" Height="16" 
    />
  <ContentPresenter 
    Content="{Binding Path=DisplayName}" 
    VerticalAlignment="Center" 
    />
</DockPanel>
</DataTemplate>

<!--
This template explains how to render the 'Workspace' content area in the main window.
-->
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl 
  IsSynchronizedWithCurrentItem="True" 
  ItemsSource="{Binding}" 
  ItemTemplate="{StaticResource ClosableTabItemTemplate}"
  Margin="4"
  />
</DataTemplate>
Tawani
  • 11,067
  • 20
  • 82
  • 106
  • 2
    Although for the time being I consider this to be part of the "Dark Arts", it is working after quite a bit of reading and playing around. I'm sure I just need to get used to this way of thinking, and just need to accept this as part of the Winforms to WPF change over. – Russ Jun 02 '09 at 14:11
  • 3
    I wonder why he bound the title of the TabItem to DisplayName and not the Header property of the TabItem instead. – Sam Dec 16 '10 at 15:21
  • Simple and elegant. This was the easiest solution I came across and worked like a charm. – Shakti Prakash Singh Apr 14 '12 at 13:15
  • My Tabcontrol seems to render its normal close button X next to the one from the template. Dont know why. – Poul K. Sørensen Mar 31 '13 at 11:58
0

Just ran into that one. I'm doing MVVM but it would be very simular to use form events. In any event I used the ItemContainerStyle parameter and point it to a style with a datatype qualifier like so:

  <Style x:Key="TabHeader" TargetType="TabItem">
        <Setter Property="FieldLayoutSettings">
            <Setter.Value>
                <StackPanel Orientation="Horizontial">
                    <TextBlock Text="{Binding HeaderText}"/>
                    <!-- MVVM style -->
                    <Button Content="X" Command="{Binding [ICommandHere]}" />
                    <!--or... Forms style -->    
                    <Button Content="X" Click="EventHandlerHere" />
             </StackPanel>
            </Setter.Value>
            </Setter> 
    </Style>

<TabControl ItemsSource="{Binding Workspaces}"
            ItemContainerStyle="{StaticResource TabHeader}"/>
Ryan Mrachek
  • 761
  • 1
  • 7
  • 17
  • 1
    Error: "FieldLayoutSettings could not be found on TabItem". Pity, it looked good. – Sam Dec 16 '10 at 15:03
  • Not sure what that mean but I found out that `FieldLayoutSettings` is often associated with the namespace `igDP` which is defined as `xmlns:igDP="http://infragistics.com/DataPresenter"`. Hope that will help other readers. – rekire Apr 21 '12 at 18:45
0

you will have to derive your own tab control. google search reveals many results, many of them with source so you dont have to re-create the wheel.

Muad'Dib
  • 28,542
  • 5
  • 55
  • 68
0

Josh Smith wrote an article for MSDN Magazine with a working example of tab items that have close buttons. The code is based on the MVVM pattern, but you should be able to extract the relevant pieces from the tab item control template.

I don't have an OpenID login so I couldn't post the URL directly. Google search for "josh smith mvvm demo app".

0

Not to hijack the thread, but you might want to consider how ugly things look when every tab has a close button. If you'd instead prefer a single close button (a la Visual Studio) integrated into the TabControl itself, you can take a look at this blog post I did, which does that as part of the sample (but is not the focus of the post).

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 3
    I hear what your saying, but I am finding that almost all tabed applications I run accross, ( IE, and FireFox being good examples ), have the option to "x" out of a tab directly on the tab itself. I personaly think it brings the action into context with the container. – Russ Jun 01 '09 at 15:24
  • 2
    Fair enough. Hiding the button until the user mouses over certainly alleviates the ugliness, too. – Kent Boogaart Jun 01 '09 at 15:31
  • That's really where I want to end up, but I'm taking this one step at a time. – Russ Jun 01 '09 at 17:03
  • 3
    I'm going to have to disagree with you. I hate it when the close button isn't with the tab itself. – Jonathan Allen Feb 17 '10 at 07:35