简体   繁体   English

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

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

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

Here is the sample XAML for my UserControl: 以下是我的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>

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

Doing this using the above XAML does not work. 使用上述XAML执行此操作不起作用。 Any ideas? 有任何想法吗?

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: 第一种是声明UIElement类型的DependencyProperty ,其中所有控件都扩展:

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: 第二种是在XAML中声明要在其中显示内容的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>

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. 在我看来,如果您使用StackPanel ,您可能会发现您的内容无法正确显示...我建议您使用Grid进行布局,除了最简单的布局任务。

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 . InnerContent属性的类型为UIElement ,这意味着它可以包含一个 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: 添加一个具有Tag属性设置的Button ,如我已经向您展示的那样:

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

Now add a Click handler: 现在添加一个Click处理程序:

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

That's all there is to it. 这里的所有都是它的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM