UserControl中的ContentPresenter

时间:2012-07-19 09:57:03

标签: c# wpf xaml contentpresenter

我是WPF的新手,我正在尝试创建一个具有一些嵌套内容的UserControl。

<my:InformationBox Header="General Information" Width="280">
    <StackPanel>
        <Label>Label1</Label>
        <Label>Label2</Label>
    </StackPanel>
</my:InformationBox>

如您所见,我想将StackPanel放入其中。当我阅读一些文章时,我应该将ContentPresenter添加到我的UserControl,所以我做了,但我找不到应该绑定到它的Content属性。

这是我的UserControl代码

<UserControl x:Class="ITMAN.InformationBox"
             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="280" Name="infoBox" Loaded="infoBox_Loaded">
    <StackPanel Width="{Binding ElementName=infoBox, Path=Width}" HorizontalAlignment="Stretch">
        <Label Content="{Binding ElementName=infoBox, Path=Header}" />
        <Border BorderThickness="0,1,0,0" Padding="10 5" Margin="5 0 5 10" BorderBrush="#B4CEDE">
            <StackPanel>
                <ContentPresenter Content="{Binding Content}" />
                <Label Content="End" />
            </StackPanel>
        </Border>
    </StackPanel>
</UserControl>

我已尝试过各种文章中的许多组合,但我找不到任何我希望实现的实例。

其他用户之前曾问过类似问题,但鉴于此答案对我没有帮助:Does anyone have a simple example of a UserControl with a single ContentPresenter?

3 个答案:

答案 0 :(得分:10)

我通过将自定义样式应用到GroupBox来解决了这个问题。我在ResourceDictionary中创建了Syle,如下所示

<Style x:Key="InformationBoxStyle" TargetType="GroupBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GroupBox">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Label>
                        <ContentPresenter Margin="4" ContentSource="Header"
                               RecognizesAccessKey="True" />
                    </Label>
                    <Border Grid.Row="1" BorderThickness="0,1,0,0" Padding="10 5"
                               Margin="5 0 5 10" BorderBrush="#B4CEDE">
                        <StackPanel>
                            <ContentPresenter />
                        </StackPanel>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

并将此样式应用于GroupBox

<GroupBox Header="General Information" Width="280" Style="{StaticResource InformationBoxStyle}">
    <StackPanel>
        <Label>Label1</Label>
        <Label>Label2</Label>
    </StackPanel>
</GroupBox>

此代码按预期工作

你也可以参考这篇很棒的文章,它展示了实现它的不同选择: http://www.codeproject.com/Articles/82464/How-to-Embed-Arbitrary-Content-in-a-WPF-Control 它还描述了ContentPresenter在我的代码中不起作用的原因。

答案 1 :(得分:9)

ContentPresenter是一种神奇的控制。如果您不向其提供任何内容,它会自动将ContentContentTemplateContentTemplateSelector属性设置为TemplateBinding到TemplatedParent。这意味着,你不需要提供任何东西,只需

<ContentPresenter/>
在UserControl中

,它应该自动使用UserControl中的相应属性。 还记得像{Binding Content}这样的绑定总是引用你的DataContext,我想这不是你想要的。

答案 2 :(得分:1)

您需要在诸如InnerContent之类的UserControl代码上创建依赖项属性。

    public object InnerContent
    {
        get { return GetValue(InnerContentProperty); }
        set { SetValue(InnerContentProperty, value); }
    }

    public static readonly DependencyProperty InnerContentProperty =
        DependencyProperty.Register("InnerContent", typeof(object), typeof(ConfirmationControl), new PropertyMetadata(null));

然后你需要绑定到UserControl的XAML端的InnerContent。

 <ContentControl Content="{Binding InnerContent, ElementName=userControl}" />

然后当您使用它而不是直接在UserControl中放置内容并覆盖现有内容时,只需将其添加到InnerContent部分。

    <UserControls:InformationBox>
        <UserControls:InformationBox.InnerContent>
            <TextBlock Text="I'm in the InnerContent" />
        </UserControls:InformationBox.InnerContent>
    </UserControls:InformationBox>

否则使用模板或样式也同样好但如果您想要打包UserControl而不强迫任何人也引用样式或模板,这可能是您更好的选择之一。