How to add controls dynamically to a UserControl through user's XAML?

c#, user-controls, wpf, xaml

Solution

You can do that, although not quite like your example. You need two things. The first is to declare a `DependencyProperty` of type `UIElement`, of which all controls extend:

public static DependencyProperty InnerContentProperty = DependencyProperty.Register("InnerContent", typeof(UIElement), typeof(YourControl));

public UIElement InnerContent
{
    get { return (UIElement)GetValue(InnerContentProperty); }
    set { SetValue(InnerContentProperty, value); }
}

The second is to declare a `ContentControl` in the XAML where you want the content to appear:

<StackPanel>
    <TextBlock Text="I want the user to be able to add any number of controls to the  StackPanel below this TextBlock."
               FontFamily="Arial" FontSize="12" FontWeight="DemiBold" Margin="5,10,5,10" TextWrapping="Wrap"/>
    <StackPanel>
        <ContentControl Content="{Binding InnerContent, RelativeSource={RelativeSource AncestorType={x:Type YourXmlNamspacePrefix:ContentView}}}" />
    </StackPanel>
</StackPanel>

In my opinion, if you use `StackPanel`s, you could find that your content does not get displayed correctly... I'd advise you to use `Grid`s for layout purposes for all but the simplest layout tasks.

Now the one difference to your example is in how you would use your control. The `InnerContent` property is of type `UIElement`, which means that it can hold one `UIElement`. This means that you need to use a container element to display more than one item, but it has the same end result:

<YourXmlNamspacePrefix:YourControl>
    <YourXmlNamspacePrefix:YourControl.InnerContent>
        <StackPanel x:Name="MyUserControl_Test" Margin="10" Height="100">
            <Button Content="Click" Height="30" Width="50"/>
            <Button Content="Click" Height="30" Width="50"/>
            <Button Content="Click" Height="30" Width="50"/>
        </StackPanel>
    </YourXmlNamspacePrefix:YourControl.InnerContent>
</YourXmlNamspacePrefix:YourControl>

And the result:

UPDATE >>>

For the record, I know exactly what you want to do. You, it seems, do not understand what I am saying, so I'll try to explain it one last time for you. Add a `Button` with the `Tag` property set as I've already shown you:

<Button Tag="MyButton1" Content="Click" Click="ButtonClick" />

Now add a `Click` handler:

private void ButtonClick(object sender, RoutedEventArgs e)
{
    Button button = (Button)sender;
    if (button.Tag = "MyButton1") DoSomething();
}

That's all there is to it.

Problem

I want to create a user control that contains a TextBlock and a StackPanel that will allow the user to add his/her own controls to the user control dynamically in XAML. Here is the sample XAML for my UserControl: ``` <UserControl x:Class="A1UserControlLibrary.UserControlStackPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="300"> <StackPanel> <TextBlock Text="I want the user to be able to add any number of controls to the StackPanel below this TextBlock." FontFamily="Arial" FontSize="12" FontWeight="DemiBold" Margin="5,10,5,10" TextWrapping="Wrap"/> <StackPanel> <!-- I want the user to be able to add any number of controls here --> </StackPanel> </StackPanel> </UserControl> ``` I would like the user to be able to embed this user control in their XAML and add their own controls to the stack panel of the user control: ``` <uc:A1UserControl_StackPanel x:Name="MyUserControl_Test" Margin="10" Height="100"> <Button Name="MyButton1" Content="Click" Height="30" Width="50"/> <Button Name="MyButton2" Content="Click" Height="30" Width="50"/> <Button Name="MyButton3" Content="Click" Height="30" Width="50"/> </uc:A1UserControl_StackPanel> ``` Doing this using the above XAML does not work. Any ideas?

Original source