How to create a WPF UserControl with NAMED content
Another alternative I've used is to just set the Name
property in the Loaded
event.
In my case, I had a rather complex control which I didn't want to create in the code-behind, and it looked for an optional control with a specific name for certain behavior, and since I noticed I could set the name in a DataTemplate
I figured I could do it in the Loaded
event too.
private void Button_Loaded(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
b.Name = "buttonName";
}
Sometimes you might just need to reference the element from C#. Depending on the use case, you can then set an x:Uid
instead of an x:Name
and access the elements by calling a Uid finder method like Get object by its Uid in WPF.
It seems this is not possible when XAML is used. Custom controls seem to be a overkill when I actually have all the controls I need, but just need to group them together with a small bit of logic and allow named content.
The solution on JD's blog as mackenir suggests, seems to have the best compromise. A way to extend JD's solution to allow controls to still be defined in XAML could be as follows:
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
var grid = new Grid();
var content = new ContentPresenter
{
Content = Content
};
var userControl = new UserControlDefinedInXAML();
userControl.aStackPanel.Children.Add(content);
grid.Children.Add(userControl);
Content = grid;
}
In my example above I have created a user control called UserControlDefinedInXAML which is define like any normal user controls using XAML. In my UserControlDefinedInXAML I have a StackPanel called aStackPanel within which I want my named content to appear.
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(MyFunkyControl), new PropertyMetadata(HeadingChanged));
private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyFunkyControl) 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:MyFunkyControl">
<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>