如何通过用户的XAML动态地向UserControl添加控件?

Pet*_*ilt 5 c# wpf xaml user-controls

我想创建一个包含TextBlock和StackPanel的用户控件,该控件允许用户在XAML中动态地将他/她自己的控件添加到用户控件.

以下是我的UserControl的示例XAML:

<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>
Run Code Online (Sandbox Code Playgroud)

我希望用户能够将此用户控件嵌入到他们的XAML中,并将他们自己的控件添加到用户控件的堆栈面板中:

<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>
Run Code Online (Sandbox Code Playgroud)

使用上述XAML执行此操作不起作用.有任何想法吗?

She*_*dan 6

可以做到这一点,虽然不是喜欢你的榜样.你需要两件事.第一种是声明一个DependencyProperty类型UIElement,所有控件都扩展为:

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

public UIElement InnerContent
{
    get { return (UIElement)GetValue(InnerContentProperty); }
    set { SetValue(InnerContentProperty, value); }
}
Run Code Online (Sandbox Code Playgroud)

第二种是ContentControl在XAML中声明要显示内容的位置:

<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>
Run Code Online (Sandbox Code Playgroud)

在我看来,如果您使用StackPanels,您发现您的内容无法正确显示...我建议您使用Grids进行布局,除了最简单的布局任务.

现在,与您的示例的一个区别在于您将如何使用您的控件.该InnerContent属性的类型的UIElement,这意味着它可以容纳一个 UIElement.这意味着您需要使用容器元素来显示多个项目,但它具有相同的最终结果:

<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>
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此输入图像描述


更新>>>

为了记录,我确切地知道你想做什么.你似乎不明白在说什么,所以我会试着最后一次为你解释.添加一个ButtonTag属性集,因为我已经向您展示:

<Button Tag="MyButton1" Content="Click" Click="ButtonClick" />
Run Code Online (Sandbox Code Playgroud)

现在添加Click处理程序:

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

这里的所有都是它的.