В чем разница между ContentControl и ContentPresenter?
-
18-09-2019 - |
Вопрос
Я не уверен, когда мне следует использовать ContentPresenter
вместо того, чтобы ContentControl
(и наоборот).На данный момент я использую ContentControl
почти все время в моем DataTemplate
s.Когда бы ContentPresenter
быть лучшим выбором?и почему?
Решение
ContentControl
является базовым классом для элементов управления, которые содержат другие элементы и имеют Content
-имущество (например, Button
).
ContentPresenter
используется внутри шаблонов элементов управления для отображения содержимого.
ContentControl
, при прямом использовании (он должен использоваться в качестве базового класса), имеет шаблон элемента управления, который использует ContentPresenter для отображения своего содержимого.
Мои практические правила (не применимы в каждом случае, судите сами):
- Внутри
ControlTemplate
использоватьContentPresenter
- Вне
ControlTemplate
(включаяDataTemplate
и внешние шаблоны) постарайтесь не использовать ни один из них, если вам нужно, вы должны предпочестьContentPresenter
- Подкласс
ContentControl
если вы создаете собственный «безобразный» элемент управления, в котором размещается контент, и вы не можете получить тот же результат, изменив существующий шаблон элемента управления (это должно быть крайне редко).
Другие советы
ContentPresenter обычно используется в ControlTemplate в качестве заполнителя, говорящего «поместите сюда фактическое содержимое».
ContentControl можно использовать где угодно, не обязательно в шаблоне.Он подберет любой DataTemplate, определенный для назначенного ему типа контента.
Недавно я написал пост в своем блоге об этих двух элементах управления:
ContentPresenter vs ContentControl (РЕДАКТИРОВАТЬ:Неработающая ссылка заменена на архивированную версию.)
Тот Самый ContentPresenter.Источник контента это то, что на самом деле составляет самую большую разницу между этими двумя классами.Свойство ContentSource имеет смысл только в ControlTemplate;он определяет, с каким свойством TemplatedParent должно быть сопоставлено содержимое.Например, если элемент управления содержит свойство зависимости MyProperty1
, тогда мы могли бы найти следующее в пределах его ControlTemplate
:
<ControlTemplate TargetType="MyControl" >
[...]
<ContentPresenter ContentSource="MyProperty1" />
[...]
</ControlTemplate>
Содержимое ContentPresenter получит значение MyProperty1
.
Пожалуйста, обратите внимание, что если название объекта недвижимости Content
, нет необходимости указывать ContentSource
поскольку это значение по умолчанию.
Для тех, кто знает AngularJS:это похоже на преодоление меканизма.
Иногда пример проще, чем теоретический жаргон.На веб-сайте MS (прокрутите вниз: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx), в качестве примера используется кнопка.Кнопка имеет ContentControl, который позволяет вам разместить один элемент управления или пользовательский элемент управления, который может быть изображением, текстом, флажком, StackPanel, сеткой и т. д.
После настройки Button теперь в 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 позволяет вводить только текст.
Это старый вопрос, но я только что заканчивал разработку анимированного элемента управления плиткой, шаблона, основанного на универсальном приложении. Посмотрите на этот код из старого SDK Phone WP7/8:
<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 также можно использовать для отображения контента, но тогда он служит и контейнером, и презентатором.Таким образом, в приведенном выше примере кода его цель разделена на Контейнер и Презентер.В динамических примерах вы можете отобразить контейнер (он может иметь пустой фон или что-то еще, чего там еще нет), а затем динамически заполнить его содержимым презентатора.У контейнера есть размеры (ширина, высота и т. д.), вы помещаете эти свойства в элемент управления контейнера и представляете в нем содержимое.В примере ContentControl определяет, что нужно сделать с содержимым презентатора.