В чем разница между ContentControl и ContentPresenter?

Я не уверен, когда я должен использовать ContentPresenter вместо ContentControl (и наоборот). На данный момент я использую ContentControl почти все время в моей DataTemplates. Когда бы ContentPresenter быть лучшим выбором? и почему?

5 ответов


ContentControl является базовым классом для элементов управления, которые содержат другие элементы и Content-имущества (например, Button).

ContentPresenter используется внутри шаблонов управления для отображения содержимого.

ContentControl, при непосредственном использовании (он должен использоваться как базовый класс), имеет шаблон элемента управления, который использует ContentPresenter для отображения его содержимого.

мои эмпирические правила (не применимые в каждом случае, используйте суд):

  1. внутри ControlTemplate использовать ContentPresenter
  2. за пределами ControlTemplate (включая DataTemplate и внешние шаблоны) старайтесь не использовать ни один из них, если вам нужно, вы должны предпочесть ContentPresenter
  3. подкласс ContentControl Если вы создаете пользовательский элемент управления "lookless", который содержит контент, и вы не можете получить тот же результат, изменив шаблон существующего элемента управления (это должно быть крайне редко).

ContentPresenter обычно используется в ControlTemplate, как заполнитель, чтобы сказать"поместите фактическое содержимое здесь".

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


недавно я написал сообщение в своем блоге об этих двух элементах управления:

ContentPresenter vs ContentControl (EDIT: сломанная ссылка заменена на архивную версию.)

на управления contentpresenter.ContentSource что на самом деле делает большое различие между двумя классами. Свойство ContentSource имеет смысл только в ControlTemplate; оно определяет, с каким свойством TemplatedParent должно сопоставляться содержимое. Например, если элемент управления содержит свойство зависимостей MyProperty1, тогда мы могли бы найти следующее в его ControlTemplate:

<ControlTemplate TargetType="MyControl" >
    [...]
       <ContentPresenter ContentSource="MyProperty1" />
    [...]
</ControlTemplate>

содержимое ContentPresenter получит значение MyProperty1.

обратите внимание, что если название отеля Content, нет необходимости указывать ContentSource как это значение по умолчанию.

для тех, кто знает angularJs: это похоже на transclude mecanism.


иногда пример проще, чем теоретический жаргон. На веб-сайте MS (прокрутите вниз: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs. 110).aspx), он использует кнопку в качестве примера. Кнопка имеет ContentControl, который позволяет разместить один элемент управления или пользовательский элемент управления, который может быть изображение, текст, флажок, StackPanel, сетка, что угодно.

после настройки кнопки, теперь на Xaml, вы можете пиши

<my:Button>
   <my:Button.Content>
      <my:AnotherControl>
   </my:Button.Content>
</my:Button>

в приведенном выше примере кода, " my:Button.Content " - это ContentControl. AnotherControl будет местом для того, что вы указали, где находится ContentPresenter.

аналогично, когда сравнивает TextBox и TextBlock, TextBox имеет ContentPresenter для вас, чтобы набивать вещи в нем так же, как в приведенном выше примере кнопки, тогда как TextBlock этого не делает. TextBlock позволяет вводить только текст.


это старый вопрос, но я только что закончил разработку анимированного элемента управления плитки, шаблона на основе универсального приложения, посмотрите на этот код со старого телефона WP7 / 8 SDK:

<ContentControl x:Name="contentControl" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch">
    <ContentPresenter x:Name="contentPresenter" CacheMode="BitmapCache"/>
</ContentControl>

здесь вы можете увидеть, что ContentControl-это контейнер и презентатор для отображения содержимого. В большинстве случаев ControlTemplate будет контейнером, но если вы хотите в своем ControlTemplate другой контейнер вы можете поместить дополнительный контейнер:ContentControl в нем и для представления контента отдельный ContentPresenter. Если вам не нужен отдельный контейнер, просто используйте ControlTemplate и ControlPresenters для отображения блоков контента, по крайней мере, это то, что ребята в Microsoft сделали, когда они разработали WP7/8 SDK. ContentControl также может использоваться для отображения содержимого, но затем он служит как контейнером, так и презентатором. Таким образом, в примере кода выше его назначение разбивается на контейнер и презентатор. В динамических образцах вы можете отобразить контейнер (он может иметь пустой фон или что-то, чего там нет пока), а затем динамически заполнять его содержимым presenter. Контейнер имеет размеры (ширина,высота и т. д.), вы помещаете эти свойства в элемент управления контейнером и представляете на нем содержимое. В Примере ContentControl определяет, что необходимо сделать с содержимым presenter.