TabItem in a separate XAML

Is it possible to put a TabItem into a separate XAML and reference something like this:

<TabControl>
     <local:MyTabItem/>
</TabControl>



In Separate XAML:
<UserControl x:Class="MyProject.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TabItem Header="MyTab">

    </TabItem>
</UserControl>

Of course it doesn't work, but I am wondering how can I do this?


If what you want to do is simply make the code more manageable then I would recommend defining each tab's data in a user control, but still have the TabItem in the main tab control.

Let's assume that your original code was this:

<TabControl>
    <TabItem Header="Tab 1">
        <Grid>
            <TextBlock Text="Tab Data" />
        </Grid>
    </TabItem>
</TabControl>

To make the code more manageable you could break the tab contents into a UserControl such as:

<UserControl x:Class="WpfApplication19.Tab1Data"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Grid>
        <TextBlock Text="Tab Data" />
    </Grid>
</UserControl>

And then use that user control in your TabControl like this:

    <TabControl>
        <TabItem Header="Tab 1">
            <tabData:Tab1Data />
        </TabItem>
    </TabControl>

If you really want to include the TabItem in your user control then you can do that by first creating a user control, and then change the type of the user control to the type TabItem (make sure you change this in both the xaml root node and the code behind).

This would leave you with a tab control that looks like this:

    <TabControl>
        <tabData:TabItem1 />
        <tabData:TabItem2 />
        <tabData:TabItem3 />
    </TabControl>

And each TabItem1 'User Control' would be of type TabItem. Here is an example:

<TabItem x:Class="WpfApplication19.TabItem1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Header="Tab 1"
         >
    <Grid>
        <TextBlock Text="Tab Data" />
    </Grid>
</TabItem>

And as I mentioned, be sure to change the code behind so that it extends TabItem instead of user control:

public partial class TabItem1 : TabItem
{
    public TabItem1()
    {
        InitializeComponent();
    }
}

The previous answer from Tony Borres already covers the most important aspects. But the further comment asks for access from code behind. So I will extend the example from Tony to show this aspect, too. This answer shows the required namespaces. I have added them to the answer from Tony, too.

To simply make the code more manageable it is recommended to define each tab's data in a user control, but still have the TabItem in the main tab control. This strategy is useful for example to work around FxCop CA1505: "Avoid unmaintainable code" when using a tab control with several tab items.

Let's assume that this is the original code:

<Window x:Class="WpfApplication19.MainWindow" ...>
    <TabControl>
        <TabItem Header="Tab 1">
            <Grid>
                <TextBlock Text="Data on Tab 1" Name="txtData1" />
            </Grid>
        </TabItem>
        <TabItem Header="Tab 2">
            <Grid>
                <TextBlock Text="Data on Tab 2" Name="txtData2" />
            </Grid>
        </TabItem>
    </TabControl>
</Window>

To make the code more manageable the tab contents can be moved into a UserControl such as:

<UserControl x:Class="WpfApplication19.Tab1Data"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Loaded="OnControlLoaded"
             >
    <Grid>
        <TextBlock Text="Data on Tab 1" Name="txtData1" />
    </Grid>
</UserControl>

And then is possible to use the new user control in the TabControl like this:

<Window x:Class="WpfApplication19.MainWindow"
        xmlns:tabData="clr-namespace:WpfApplication19" ...>
    <TabControl>
        <TabItem Header="Tab 1">
            <tabData:Tab1Data x:Name="ucTab1Data" />
        </TabItem>
        <TabItem Header="Tab 2">
            <Grid>
                <TextBlock Text="Data on Tab 2" Name="txtData2"/>
            </Grid>
        </TabItem>
    </TabControl>
</Window>

Now it possible to access the inner wigdets of the user control from main window and vice versa. Please note the "x:" in front of the user control's name.

public partial class MainWindow : Window
{
    private void AccessWidgetWithinUserControl()
    {
        ucTab1Data.txtData1.Text = "New text on Tab 1";
    }
}

public partial class Tab1Data : UserControl
{
    private MainWindow mainWindow = null; // Reference to the MainWindow

    public Tab1Data()
    {
        InitializeComponent();
    }

    // get a reference to main windows when it is available.
    // The Loaded Event is set in the XAML code above.
    private void OnControlLoaded(object sender, RoutedEventArgs e)
    {
        mainWindow = Window.GetWindow(this) as MainWindow;
    }

    private void AccessMainWindowsWidget()
    {
        mainWindow.txtData2.Text = "New text on Tab 2 in the main window";
    }
}

The shown code to access txtData2 would be the same even if is embedded in its own user control.


On the surface this sounds like it would be best solved by a a style and/or template for the TabItem control which you can store in a separate resource file. How much you need to customize the actual TabItem will determine if you can just use a style or if you need a template.

What you can do is define a named Style for each TabItem in a separate resource file like so, create a MyResources.xaml that looks something like this:

<ResourceDictionary>
    <Style x:Key="MyTabItem" TargetType="{x:Type TabItem}">
      <!-- 
           you can just use simple property setters to set up 
           the TabItem or set the Template property to replace
           entire tab look and feel
      -->
    </Style>
</ResourceDictionary>

Then in your main App.xaml file you merge in the resource dictionary:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MyResources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Finally in your application you would leverage these Styles by simply doing:

<TabItem Style="{DynamicResource MyTabItem}" />

I think what you wanted is to get TabItem Content declare separately. Since TabItem is a ContentControl you can present a UserControl as its content.

<TabControl>
   <TabItem> 
       <local:YourTabContent1/>
   </TabItem>
   <TabItem> 
       <local:YourTabContent2/>
   </TabItem>
</TabControl>

In Separate XAML:

<UserControl x:Class="MyProject.YourTabContent1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <......blah blah.../>
</UserControl>

In another XAML you can have content 2

<UserControl x:Class="MyProject.YourTabContent2"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <......blah blah.../>
</UserControl>