WPF:自定义控件中的多个内容呈现器?

13

我试图创建一个自定义控件,需要使用一个继承自该控件的子控件来定义XAML中的2个或多个区域。我想知道是否有一种方法可以定义多个内容呈现器,并且其中一个作为默认内容呈现器。

<MyControl>
      <MyControl.MyContentPresenter2>
           <Button Content="I am inside the second content presenter!"/>
      </MyControl.MyContentPresenter2>

      <Button Content="I am inside default content presenter" />
</MyControl>

这是否可行,我该如何在自定义控件的模板中定义它?

3个回答

14

模板可以像这样绑定独立的ContentPresenter实例(此处仅设置了一个属性,但您可能想设置其他属性):

<ContentPresenter Content="{TemplateBinding Content1}"/>
<ContentPresenter Content="{TemplateBinding Content2}"/>

控件本身应该使用ContentPropertyAttribute公开两个属性以用于内容,并使用默认值进行设置:

[ContentProperty("Content1")]
public class MyControl : Control
{
    // dependency properties for Content1 and Content2
    // you might also want Content1Template, Content2Template, Content1TemplateSelector, Content2TemplateSelector
}

3
你可以使用ContentSource属性来更直接地完成这个操作,这样做的好处是还支持用于内容的模板和模板选择器。 - mancaus
1
Kent,我不需要设置ContentProperty属性,因为它已经设置为“Content”。我所需要做的就是为“Content2”设置另一个依赖属性,并将其绑定到另一个内容呈现器,但感谢您指出了正确的方向。 - Shai UI
2
@foreyez:我假设您没有从“ContentControl”继承。顺便说一下,根据您的确切要求,您可以尝试使用“HeaderedContentControl”来实现。 - Kent Boogaart

6
您可以使用带有自定义模板的“ItemsControl”。
<ItemsControl>
    <ItemsControl.Style>
        <Style TargetType="ItemsControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel Orientation="Horizontal">
                            <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items[0]}"/>
                            <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items[1]}"/>
                            <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items[2]}"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.Style>
    <TextBlock Text="Item 1"/>
    <TextBlock Text="Item 2"/>
    <TextBlock Text="Item 3"/>
</ItemsControl>

3
这里提供了另一个选项,不需要创建自定义控件,比使用ItemsControl更安全(如果类型安全是您想要的东西...也许不是):
...使用附加属性!
创建适当类型的附加属性。我们恰好需要一个文本控件,所以我创建了一个字符串TextContent附加属性。然后在模板中创建一个TemplateBinding,并在Xaml中实例化时将其设置为模板绑定。效果很好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接