我可以在ContentTemplate中的单个Content或ContentSource中指向两个ContentPresenter吗?

时间:2009-02-27 17:16:04

标签: wpf contentpresenter

我创建了一个类似于Outlook 2007的NavigationPane。在Outlook中,当折叠窗格并单击侧栏时,它会用于弹出Selected NavigationItem内容。我使用ControlTemplete中的contentpresenter来模仿相同的行为(一个用于TabControl的SelectItemHost,另一个用于Popup)。但问题是当弹出窗口打开时,NavigationPane会在离开时选择内容,当我们从另一个导航项切换回相同的导航项时它会出现。我使用TabControl和TabItem作为NavigationPane和NavigationPaneItem。

我将“SelectedContent”指向两个ContentPresenter

的ContentSource

1 个答案:

答案 0 :(得分:4)

您可以在控件模板中定义两个ContentPresenter对象,如果您愿意,可以将它们指向同一个内容源:

<ControlTemplate x:Key="WeirdButton" TargetType="Button">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Border Grid.RowSpan="2" Background="{TemplateBinding Background}" />
        <ContentPresenter ContentSource="Content"/>
        <ContentPresenter ContentSource="Content" Grid.Row="1"/>
    </Grid>
</ControlTemplate>

然而,这有一些相当不寻常的副作用。因为您无法将相同的视觉效果放在可视化树中的两个位置,所以如果按钮的子内容不是可视(或从Visual派生),则此模板将仅按预期工作。如果内容是某种其他类型的数据,并且视觉效果是由数据模板生成的,则一切都按预期工作。将按钮的内容设置为字符串(<Button Content="OK"/>)也可以。

请注意,使用可视化笔刷可以实现相同的效果:

<ControlTemplate x:Key="WeirdButton" TargetType="Button">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Border Grid.RowSpan="2" Background="{TemplateBinding Background}" />
        <ContentPresenter x:Name="presenter" ContentSource="Content"/>
        <Rectangle Grid.Row="1" 
                   Width="{Binding ActualWidth, ElementName=presenter}" Height="{Binding ActualHeight, ElementName=presenter}">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=presenter}" Stretch="None" AlignmentX="Left"/>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</ControlTemplate>

此方法的缺点是您无法与可视画笔中的控件进行交互。因此,如果您希望副本上的按钮,文本框和其他控件也是交互式的,则必须遵循靠近第一个模板的方法。