I have a custom user control with two templates that I want to use together for each item in a Tab Control. I am only able to use one at a time.
CustomUserControl.xaml.cs
public partial class CustomUserControl : UserControl
{
public CustomUserControl ()
{
InitializeComponent();
var style = (Style)FindResource("Styling");
Style = style;
}
public static readonly DependencyProperty ItemHeaderTemplateProperty = DependencyProperty.Register(
nameof(ItemHeaderTemplate), typeof(DataTemplate),
typeof(ConfigurableCollectionControl), new PropertyMetadata(default(DataTemplate)));
public DataTemplate ItemHeaderTemplate
{
get => (DataTemplate) GetValue(ItemHeaderTemplateProperty);
set => SetValue(ItemHeaderTemplateProperty, value);
}
public static readonly DependencyProperty ItemContentTemplateProperty = DependencyProperty.Register(
nameof(ItemContentTemplate), typeof(DataTemplate),
typeof(ConfigurableCollectionControl), new PropertyMetadata(default(DataTemplate)));
public DataTemplate ItemContentTemplate
{
get => (DataTemplate) GetValue(ItemContentTemplateProperty);
set => SetValue(ItemContentTemplateProperty, value);
}
}
I can reference one of them in a tab control like this:
CustomUserControl.xaml
<Style x:Key="Styling" TargetType="{x:Type local:CustomUserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomUserControl}">
<TabControl Style="{Static CustomStyle}"
ItemsSource="{Binding Items}"
ContentTemplate="{TemplateBinding ItemContentTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note: I am referencing it from the main page like so: MainPage.xaml
<test:CustomUserControl Content="{Binding}"
ItemHeaderTemplate="{StaticResource TestHeaderTemplate}"
ItemContentTemplate="{StaticResource TestContentTemplate}"/>
I have tried referencing them both like this, with a DataTemplate, but the project doesn't compile:
CustomUserControl.xaml
<DataTemplate x:Key="TestTemplate" DataType="{x:Type local:CustomUserControl}">
<StackPanel>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemHeaderTemplate}"/>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemContentTemplate}"/>
</StackPanel>
</DataTemplate>
<Style x:Key="Styling" TargetType="{x:Type local:CustomUserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomUserControl}">
<TabControl Style="{Static CustomStyle}"
ItemsSource="{Binding Items}"
ContentTemplate="{StaticResource TestTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I do the same thing, but with a ControlTemplate, it will compile, but then crash when I navigate to the page:
CustomUserControl.xaml
<ControlTemplate x:Key="TestTemplate" DataType="{x:Type local:CustomUserControl}">
<StackPanel>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemHeaderTemplate}"/>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemContentTemplate}"/>
</StackPanel>
</ControlTemplate>
<Style x:Key="Styling" TargetType="{x:Type local:CustomUserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomUserControl}">
<TabControl ItemsSource="{Binding Items}"
ContentTemplate="{StaticResource TestTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It seems that ControlTemplate will allow me to reference the CustomUserControl templates, but can't use it as a ContentTemplate. While a DataTemplate can be used as a ContentTemplate, but will not allow me to reference to the CustomUserControl templates.
This led me to try using a DataTemplate with the ControlTemplate referenced inside, as follows.
CustomUserControl.xaml
<ControlTemplate x:Key="TestControlTemplate" DataType="{x:Type local:CustomUserControl}">
<StackPanel>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemHeaderTemplate}"/>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemContentTemplate}"/>
</StackPanel>
</ControlTemplate>
<DataTemplate x:Key="TestDataTemplate" DataType="{x:Type local:CustomUserControl}">
<StackPanel>
<ContentControl Template="{StaticResource TestControlTemplate}"/>
</StackPanel>
</DataTemplate>
<Style x:Key="Styling" TargetType="{x:Type local:CustomUserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomUserControl}">
<TabControl ItemsSource="{Binding Items}"
ContentTemplate="{StaticResource TestDataTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But then it crashes again. I get this message
''CustomUserControl' ControlTemplate TargetType does not match templated type 'ContentControl'.'
If I change the TargetType of the ControlTemplate to ContentControl, the project doesn't compile.
Is there a way for this to be done? Or do I need to do this a totally different way?
CodePudding user response:
I set the Name of the UserControl to UserControlName
<UserControl ...
Name="UserControlName">
I then used the Source & Path to access the ItemHeaderTemplate & ItemContentTemplate templates I had defined in the CustomUserControl
<ControlTemplate x:Key="TestControlTemplate" DataType="{x:Type local:CustomUserControl}">
<StackPanel>
<ContentControl Content="{Binding}"
ContentTemplate="{Binding Source={x:Reference UserControlName},
Path=ItemHeaderTemplate}"/>
<ContentControl Content="{Binding}"
ContentTemplate="{Binding Source={x:Reference UserControlName},
Path=ItemContentTemplate}"/>
</StackPanel>
</ControlTemplate>
<DataTemplate x:Key="TestDataTemplate" DataType="{x:Type local:CustomUserControl}">
<ContentControl Template="{StaticResource TestControlTemplate}"/>
</DataTemplate>
<Style x:Key="Styling" TargetType="{x:Type local:CustomUserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomUserControl}">
<TabControl ItemsSource="{Binding Items}"
ContentTemplate="{StaticResource TestDataTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>