Expose a UserControls ContentTemplate

Viewed 327

I'm trying to make my fist UserControl in C#. It is a TabControll with some quality of life improvements. The goal is to be able to use it in various projects, so it has to be as generic as possible.

So far I have exposed the ItemSource through a DependencyProperty. But I'm suck with how to do the same with the ContentTemplate Property.

Here's an example of my code so far:

XAML:

<UserControl ...>
    <UserControl.Resources>
        <!-- some styles and templates -->
    </UserControl.Resources>
    <TabControl ItemsSource="{Binding ItemsSource}" SelectedIndex="{Binding selectedIndex}"
            Style="{StaticResource FixatedTabControl}" ItemTemplateSelector="{StaticResource myDataTemplateSelector}"/>
</UserControl>

The code behind:

public partial class DynamicTabControl : UserControl, INotifyPropertyChanged
{
    public DynamicTabControl()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable<ITabItem>), typeof(DynamicTabControl));
        public IEnumerable<ITabItem> ItemsSource
        {
            get { return (IEnumerable<ITabItem>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
}

I can use the DynamicTabControl like so:

<Window x:Class="Demo.MainWindow"
        ...            
        xmlns:local="clr-namespace:Demo"
        xmlns:foo="clr-namespace:DynamicTabUserControl"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <foo:DynamicTabControl x:Name="testTabContr" ItemsSource="{Binding data}">

        </foo:DynamicTabControl>
    </Grid>
</Window>

But how can I make it possible to alter/add the contenTemplate of the UserControl's TabControl? I would like to get it to behave like such:

<Window x:Class="Demo.MainWindow"
            ...            
            xmlns:local="clr-namespace:Demo"
            xmlns:foo="clr-namespace:DynamicTabUserControl"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <foo:DynamicTabControl x:Name="testTabContr" ItemsSource="{Binding data}">
               <foo:DynamicTabControl.TabControl.ContentTemplate>
                   <DataTemplate>
                      <TextBox Text="{Binding someData}"/>
                   </DataTemplate>
               </foo:DynamicTabControl.TabControl.ContentTemplate>
            </foo:DynamicTabControl>
        </Grid>
    </Window>

I'm still learning, so please help me out. Thank you in advance.

1 Answers

Add another dependency property to the UserControl:

public partial class DynamicTabControl : UserControl, INotifyPropertyChanged
{
    public DynamicTabControl()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable<ITabItem>), typeof(DynamicTabControl));
    public IEnumerable<ITabItem> ItemsSource
    {
        get { return (IEnumerable<ITabItem>)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty TabContentTemplateProperty =
        DependencyProperty.Register("TabContentTemplate", typeof(DataTemplate), typeof(DynamicTabControl));

    public DataTemplate TabContentTemplate
    {
        get { return (DataTemplate)GetValue(TabContentTemplateProperty); }
        set { SetValue(TabContentTemplateProperty, value); }
    }
}

...and bind to it:

<UserControl>
    <UserControl.Resources>
        <!-- some styles and templates -->
    </UserControl.Resources>
    <TabControl ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
                Style="{StaticResource FixatedTabControl}"
                ContentTemplate="{Binding TabContentTemplate, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl>

You can then set this property in the XAML markup of the window:

<foo:DynamicTabControl x:Name="testTabContr" ItemsSource="{Binding data}">
    <foo:DynamicTabControl.TabContentTemplate>
        <DataTemplate>
            <TextBox Text="{Binding someData}"/>
        </DataTemplate>
    </foo:DynamicTabControl.TabContentTemplate>
</foo:DynamicTabControl>
Related