Search code examples
wpfimageheadertabcontroltabitem

Custom TabItem header with text and image - not sure how to proceeed


I have a TabControl in my XAML which is just an empty control as the TabItems are dynamically generated at runtime.

My problem is I want to have the tab title and an image (a "settings" image) in the Header but I'm not sure how to go about this. As I said, I'm generating the TabItems on the fly so how and where would a template to do this fit in and where would I put it etc? Would a TabItem header template apply to TabItem controls created dynamically? (I am assuming/hoping so!)

I've googled and searched around here but no-one quite seems to be doing what I'm doing... just wondering if someone could give me some guidance.

<Grid Name="MainGrid" Background="#333333" ShowGridLines="False" >
    <Grid.RowDefinitions>
        <RowDefinition Height="50"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="0" ToolTip="Settings">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="RoboNews" Foreground="SkyBlue" FontSize="32" Padding="5"/>
        <Button Name="btnSettings" Background="Transparent" Grid.Column="1" BorderBrush="#333333" BorderThickness="0" HorizontalAlignment="Right" 
                Click="btnSettings_Click" ToolTip="Click for menu">
            <!--<Image Source="Images/Settings48x48.png"/>-->
            <Image Source="/Images/MenuOpen.png" Width="36" />
        </Button>

    </Grid>

    <TabControl Name="tabCategories" Grid.Row="1" Background="Black" SelectionChanged="tabCategories_SelectionChanged">  

    </TabControl>
</Grid>

Solution

  • You can create a UserControl for your header

    <UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}" x:Class="TabControlHeader.TabItemHeader"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" Width="Auto" Height="Auto">
        <Grid >
            <StackPanel>
                <Image Source="{Binding ImageSource}"></Image>
                <TextBlock Text="{Binding Text}"></TextBlock>
            </StackPanel>
        </Grid>
    </UserControl>
    

    With ideally DPs defined in its ViewModel, but for the time being, in code behind:

    public string ImageSource
    {
        get { return (string)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }
    
    // Using a DependencyProperty as the backing store for ImageSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.Register("ImageSource", typeof(string), typeof(TabItemHeader));
    
    
    
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    
    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(TabItemHeader));
    

    Then while creating your TabItem you need to set its HeaderTemplate:

    TabItem tabItem = new TabItem();
    tabItem.Height = 100;
    tabItem.Width = 50;
    var header = new FrameworkElementFactory(typeof(TabItemHeader));
    header.SetValue(TabItemHeader.TextProperty, "This is Text");
    header.SetValue(TabItemHeader.ImageSourceProperty, "This is Image uri");
    header.SetValue(TabItemHeader.HeightProperty, (double)50);
    header.SetValue(TabItemHeader.WidthProperty, (double)50);
    
    
    tabItem.HeaderTemplate = new DataTemplate { VisualTree = header };            
    tabCategories.Items.Add(tabItem);