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

时间:2014-01-29 21:49:26

标签: 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>

我希望用户能够将此用户控件嵌入到他们的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>

使用上述XAML执行此操作不起作用。有什么想法吗?

1 个答案:

答案 0 :(得分:6)

可以这样做,虽然不像你的例子那样完全。你需要两件事。第一种是声明类型为DependencyProperty的{​​{1}},其中所有控件都会扩展:

UIElement

第二种是在XAML中声明要显示内容的public static DependencyProperty InnerContentProperty = DependencyProperty.Register("InnerContent", typeof(UIElement), typeof(YourControl)); public UIElement InnerContent { get { return (UIElement)GetValue(InnerContentProperty); } set { SetValue(InnerContentProperty, value); } }

ContentControl

在我看来,如果您使用<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> 可以发现您的内容无法正确显示...我建议您使用StackPanel s用于除最简单的布局任务之外的所有布局。

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

UIElement

结果:

enter image description here


更新&gt;&gt;&gt;

为了记录,我知道完全你想做什么。你似乎不明白在说什么,所以我会尽力为你解释最后一次。添加<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> ,其中Button属性设置为我已经向您显示的内容:

Tag

现在添加一个<Button Tag="MyButton1" Content="Click" Click="ButtonClick" /> 处理程序:

Click

这就是它的全部内容。