danbord
danbord

Reputation: 4076

ContentControl Template through Property

I have a Usercontrol with a ControlTemplate DependencyProperty (named MyItemTemplate).

public ControlTemplate MyContentControl
        {
            get { return (ControlTemplate)GetValue(MyContentControlProperty); }
            set { SetValue(MyContentControlProperty, value); }
        }
        public static readonly DependencyProperty MyContentControlProperty =
            DependencyProperty.Register("MyContentControl", typeof(ControlTemplate), typeof(MyScroll),
              new PropertyMetadata(new ControlTemplate()));

In the xaml of my UserControl I want to use the "MyItemTemplate" as a template for a ContentControl like that :

<ContentControl x:Name="MyContentControl" Template="{Binding MyItemTemplate}" />

I know that the Template="{Binding MyItemTemplate}" is wrong, but I wonder how to do it...

Thanks

Upvotes: 0

Views: 2041

Answers (3)

Pavel Gatilov
Pavel Gatilov

Reputation: 7661

Although the best answer is Rachel's, here are some alternatives.

If this logic is not critical, you'd better put the template into resources and get it using StaticResource:

<UserControl>
  <UserControl.Resources>
    <ControlTemplate x:Key="template">
      ...
    </ControlTemplate>
  </UserControl.Resources>

  <ContentControl Template="{StaticResource template}"/>
</UserControl>

If you still need to set it from the UserControl's property, you may either define a change callback. XAML:

<UserControl>
  <ContentControl x:Name="contentControl"/>
</UserControl>

Code-behind:

public ControlTemplate MyContentControl
{
  get { return (ControlTemplate)GetValue(MyContentControlProperty); }
  set { SetValue(MyContentControlProperty, value); }
}

public static readonly DependencyProperty MyContentControlProperty =
  DependencyProperty.Register("MyContentControl", typeof(ControlTemplate), typeof(MyScroll), new PropertyMetadata(null, OnMyContentControlChanged));

static void OnMyContentControlChanged(object sender, DependencyPropertyChangedEventArgs e)
{
  var userControl = (MyScroll)sender;

  userControl.contentControl.Template = e.NewValue as ControlTemplate;
}

And the last option is using a Custom Control. Code:

public class MyScroll : SomeParentControl
{
  public MyScroll()
  {
    this.DefaultStyleKey = typeof(MyScroll);
  }

  public ControlTemplate MyContentControl
  {
    get { return (ControlTemplate)GetValue(MyContentControlProperty); }
    set { SetValue(MyContentControlProperty, value); }
  }

  public static readonly DependencyProperty MyContentControlProperty =
    DependencyProperty.Register("MyContentControl", typeof(ControlTemplate), typeof(MyScroll), new PropertyMetadata(null));
}

The template:

<!-- This is a template for what have been your UserControl -->
<ControlTemplate TargetType="{x:Type someNameSpaceAlias:MyScroll}">
  <!-- And this is the 'MyContentControl' -->
  <ContentControl Template="{TemplateBinding MyContentControl}"/>
</ControlTemplate>

Upvotes: 1

Rachel
Rachel

Reputation: 132548

You can use a RelativeSource binding to reference a custom DependencyProperty on your UserControl

<ContentControl Template="{Binding 
    RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, 
    Path=MyItemTemplate}" />

Edit

If you're working in Silverlight 4.0 or lower, which doesn't support RelativeSource bindings, then give your UserControl tag a Name and use an ElementName binding

<UserControl x:Name="MyUserControl" ...>
    <ContentControl Template="{Binding ElementName=MyUserControl, Path=MyItemTemplate}" />
</UserControl>

Upvotes: 4

ChrisBD
ChrisBD

Reputation: 9209

Have your template as a static resource (defined in your XAML somewhere).

<DataTemplate x:Key="DetailedTemplate">

 <Border BorderBrush="Blue" Margin="3" Padding="3" BorderThickness="2" CornerRadius="5" Background="Beige">

 <StackPanel Orientation="Horizontal">

 <Image Margin="10" Width="250" Height="200" Stretch="Fill" Source="{Binding Path=ImageHref}">

 <Image.BitmapEffect>

 <DropShadowBitmapEffect />

 </Image.BitmapEffect>

 </Image>

 <StackPanel Orientation="Vertical" VerticalAlignment="Center">

 <TextBlock FontSize="25" Foreground="Goldenrod" Text="{Binding Path=ImageName}" />

 <Label Content="{Binding Path=ImageRating,Converter={StaticResource RatingConverter}}" />

 </StackPanel>

 </StackPanel>

 </Border>

</DataTemplate>



<DataTemplate x:Key="SimpleTemplate">

 <Border BorderBrush="Blue" Margin="3" Padding="3" BorderThickness="2" CornerRadius="5" Background="Beige">

 <StackPanel HorizontalAlignment="Center">

 <Image Margin="10" Width="250" Height="200" Stretch="Fill" Source="{Binding Path=ImageHref}">

 <Image.BitmapEffect>

 <DropShadowBitmapEffect />

 </Image.BitmapEffect>

 </Image>

 </StackPanel>

 </Border>

</DataTemplate>

For example, in XAML:

<ListBox x:Name="lbResults" Grid.Row="1" Grid.Column="0" Height="240" 

 HorizontalContentAlignment="Stretch" ItemsSource="{StaticResource FavoriteImages}" 

 ItemTemplate="{StaticResource SimpleTemplate}" />

Then in the code behind something like:

//pull the detailed template from resources, identified by the DetailedTemplate key

 DataTemplate detail = this.FindResource("DetailedTemplate") as DataTemplate;

 lbResults.ItemTemplate = detail;

and

//pull the summary template from resources, identified by the SimpleTemplate key

 DataTemplate summary = this.FindResource("SimpleTemplate") as DataTemplate;

 lbResults.ItemTemplate = summary;

Upvotes: 1

Related Questions