How to create WPF usercontrol which contains placeholders for later usage

。_饼干妹妹 提交于 2019-11-28 16:51:08

ContentControls & ItemsControls are good for this, you can bind them to a property of your UserControl or expose them.

Using a ContentControl (for placeholders in multiple disconnected places):

<UserControl x:Class="Test.UserControls.MyUserControl2"
             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" 
             Name="control">
    <Grid>
        <Button>Just a button</Button>
        <ContentControl Content="{Binding PlaceHolder1, ElementName=control}"/>
    </Grid>
</UserControl>
public partial class MyUserControl2 : UserControl
{
    public static readonly DependencyProperty PlaceHolder1Property =
        DependencyProperty.Register("PlaceHolder1", typeof(object), typeof(MyUserControl2), new UIPropertyMetadata(null));
    public object PlaceHolder1
    {
        get { return (object)GetValue(PlaceHolder1Property); }
        set { SetValue(PlaceHolder1Property, value); }
    }

    public MyUserControl2()
    {
        InitializeComponent();
    }
}
<uc:MyUserControl2>
    <uc:MyUserControl2.PlaceHolder1>
        <TextBlock Text="Test"/>
    </uc:MyUserControl2.PlaceHolder1>
</uc:MyUserControl2>

ItemsControl-Version (for collections in one place)

<UserControl x:Class="Test.UserControls.MyUserControl2"
             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"
             Name="control">
    <Grid>
        <Button>Just a button</Button>
        <ItemsControl Name="_itemsControl" ItemsSource="{Binding ItemsSource, ElementName=control}"/>
    </Grid>
</UserControl>
[ContentProperty("Items")]
public partial class MyUserControl2 : UserControl
{
    public static readonly DependencyProperty ItemsSourceProperty = 
        ItemsControl.ItemsSourceProperty.AddOwner(typeof(MyUserControl2));
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public ItemCollection Items
    {
        get { return _itemsControl.Items; }
    }

    public MyUserControl2()
    {
        InitializeComponent();
    }
}
<uc:MyUserControl2>
    <TextBlock Text="Test"/>
    <TextBlock Text="Test"/>
</uc:MyUserControl2>

With UserControls you can decide to expose certain properties of internal controls; besides the ItemsSource one probably would want to also expose properties like the ItemsControl.ItemTemplate, but it all depends on how you want to use it, if you just set the Items then you do not necessarily need any of that.

I think you want to set your UserControl's ControlTemplate with a ContentPresenter located inside (so you can define where the Content will be presented).

Your Custom UserControl:

<UserControl x:Class="TestApp11.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Template>
        <ControlTemplate>
            <StackPanel>
                <TextBlock Text="Custom Control Text Area 1" />
                <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
                <TextBlock Text="Custom Control Text Area 2" />
            </StackPanel>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

Usage:

<Window x:Class="TestApp11.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:l="clr-namespace:TestApp11"
    Title="Window1" Height="250" Width="200">
    <StackPanel>
        <l:UserControl1>
            <Button Content="My Control's Content" />
        </l:UserControl1>
    </StackPanel>
</Window>

If you need multiple items in your content section, simply place them in a container like a grid or a stackpanel:

<l:UserControl1>
    <StackPanel>
        <Button Content="Button 1" />
        <Button Content="Button 2" />
    </StackPanel>
</l:UserControl1>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!