Can I have two ContentPresenter pointing to in single Content or ContentSource in the ContentTemplate?

StackOverflow https://stackoverflow.com/questions/595701

  •  09-09-2019
  •  | 
  •  

Question

I have created a NavigationPane just like Outlook 2007. In Outlook, when the Pane is collapsed and the side bar is clicked, it used to popup the Selected NavigationItem content. I mimicked the same behavior using contentpresenter in the ControlTemplete (one for the TabControl's SelectItemHost and another for the Popup). But the problem is when the Popup is open up, the NavigationPane selected content when away and it appears when we switch back to the same navigation item from another navigation item. I am using TabControl and TabItem as NavigationPane and NavigationPaneItem.

I am pointing the "SelectedContent" as the ContentSource for the two ContentPresenter

Was it helpful?

Solution

You can define two ContentPresenter objects within a control template and point them both at the same content source if you like:

<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>

This has some rather unusual side effects, however. Because you can't put the same visual into two places in the visual tree, this template will only work as expected if the child content of the button is NOT a visual (or derived from Visual). If the content is some other type of data and the visuals are generated by a data template everything works as expected. Setting the content of the button to a string (<Button Content="OK"/>) works also.

Note that this same effect could be achieved with a visual brush:

<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>

The drawback of this approach is that you can't interact with controls in the visual brush. So if you want the buttons, textboxes, and other controls on the duplicate to also be interactive, you will have to follow an approach closer to the first template.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top