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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21443397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:40:00  来源:igfitidea点击:

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

c#wpfxamluser-controls

提问by PeterBuilt

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. Any ideas?

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

回答by Sheridan

You cando that, although not quitelike your example. You need two things. The first is to declare a DependencyPropertyof type UIElement, of which all controls extend:

可以这样做,虽然不太像你的例子。你需要两件事。第一个是声明一个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); }
}

The second is to declare a ContentControlin the XAML where you want the content to appear:

第二种是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>

In my opinion, if you use StackPanels, you couldfind that your content does not get displayed correctly... I'd advise you to use Grids for layout purposes for all but the simplest layout tasks.

在我看来,如果您使用StackPanels,您发现您的内容无法正确显示...我建议您将Grids 用于布局目的,但最简单的布局任务除外。

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

现在,与您的示例的一个不同之处在于您将如何使用您的控件。该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>

And the result:

结果:

enter image description here

在此处输入图片说明



UPDATE >>>

更新 >>>

For the record, I know exactlywhat you want to do. You, it seems, do not understand what Iam saying, so I'll try to explain it one last timefor you. Add a Buttonwith the Tagproperty set as I've already shown you:

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

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

Now add a Clickhandler:

现在添加一个Click处理程序:

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

That's all there is to it.

这里的所有都是它的。