views:

2529

answers:

1

I know how to create a custom user control in WPF but how can I make it so that someone can provide an ItemTemplate?

I have a user control that is a mixture of several other WPF controls, one of them being a ListBox. I'd like to let the user of the control specify the content of the list box but I'm not sure how to pass that information through.

EDIT: The accepted answer works with the following correction:

<UserControl x:Class="WpfApplication6.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication6">
    <ListBox ItemTemplate="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:MyControl}}, Path=ItemsSource}" />
</UserControl>
+6  A: 

You will want to add a DependencyProperty to your control. The xaml will look slightly different if you are deriving from UserControl or Control.

public partial class MyControl : UserControl
{
 public MyControl()
 {
  InitializeComponent();
 }

 public static readonly DependencyProperty ItemTemplateProperty =
  DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(MyControl), new UIPropertyMetadata(null));
 public DataTemplate ItemTemplate
 {
  get { return (DataTemplate) GetValue(ItemTemplateProperty); }
  set { SetValue(ItemTemplateProperty, value); }
 }
}

Here is xaml for a UserControl.

<UserControl x:Class="WpfApplication6.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication6">
    <ListBox ItemTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:MyControl}}}" />
</UserControl>

Here is xaml for a Control:

<Style TargetType="{x:Type src:MyControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type src:MyControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">

     <ListBox ItemTemplate="{TemplateBinding ItemTemplate}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Todd White
that's not nearly as bad as I was making it out to be. I'll accept after I'm able to verify that it works.
Justin Bozonier
Okay, I got this working but there was one correction I needed to make. I'm going to post it in my original question.
Justin Bozonier
Oh right I forgot the property on ItemTemplate binding. I'll fix my answer too.
Todd White