Могу ли я иметь два ContentPresenter, указывающие на один Content или ContentSource в ContentTemplate?

Я создал NavigationPane точно так же, как Outlook 2007. В Outlook, когда панель свернута и нажата боковая панель, она использовалась для вызова содержимого Selected NavigationItem. Я имитировал то же поведение, используя contentpresenter в ControlTemplete (один для SelectItemHost TabControl и другой для Popup). Но проблема в том, что когда всплывающее окно открыто, NavigationPane выбирает содержимое, когда оно отсутствует, и оно появляется, когда мы снова переключаемся на тот же элемент навигации с другого элемента навигации. Я использую TabControl и TabItem в качестве NavigationPane и NavigationPaneItem.

Я указываю "SelectedContent" как ContentSource для двух ContentPresenter

1 ответ

Решение

Вы можете определить два 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>

Недостаток этого подхода заключается в том, что вы не можете взаимодействовать с элементами управления в визуальной кисти. Поэтому, если вы хотите, чтобы кнопки, текстовые поля и другие элементы управления на дубликате также были интерактивными, вам нужно будет придерживаться подхода, более близкого к первому шаблону.

Другие вопросы по тегам