I have a set of controls with attached commands and logic that are constantly reused in the same way. I decided to create a user control that holds all the common controls and logic.
However I also need the control to be able to hold content that can be named. I tried the following:
<UserControl.ContentTemplate>
<DataTemplate>
<Button>a reused button</Button>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Button>a reused button</Button>
</DataTemplate>
</UserControl.ContentTemplate>
However it seems any content placed inside the user control cannot be named. For example if I use the control in the following way:
<lib:UserControl1>
<Button Name="buttonName">content</Button>
</lib:UserControl1>
I receive the following error:
Cannot set Name attribute value 'buttonName' on element 'Button'. 'Button' is under the scope of element 'UserControl1', which already had a name registered when it was defined in another scope.
If I remove the buttonName, then it compiles, however I need to be able to name the content. How can I achieve this?
The answer is to not use a UserControl to do it.
Create a class that extends ContentControl
public class MyFunkyControl : ContentControl
{
public static readonly DependencyProperty HeadingProperty =
DependencyProperty.Register("Heading", typeof(string),
typeof(HeadingContainer), new PropertyMetadata(HeadingChanged));
private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((HeadingContainer) d).Heading = e.NewValue as string;
}
public string Heading { get; set; }
}
then use a style to specify the contents
<Style TargetType="control:MyFunkyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="control:MyFunkyContainer">
<Grid>
<ContentControl Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and finally - use it
<control:MyFunkyControl Heading="Some heading!">
<Label Name="WithAName">Some cool content</Label>
</control:MyFunkyControl>