Яка різниця між ContentControl та ContentPresenter?


208

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

Відповіді:


164

ContentControlє базовим класом для елементів керування, які містять інші елементи та мають Content-властивість (наприклад, Button).

ContentPresenter використовується у шаблонах управління для відображення вмісту.

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

Мої правила (не застосовується в кожному випадку, використовуйте ваше судження):

  1. Внутрішнє ControlTemplateвикористанняContentPresenter
  2. Поза межами ControlTemplate(включаючи DataTemplateшаблони і за їх межами) намагайтеся не використовувати жоден із них, якщо вам потрібно, ви повинні віддати перевагуContentPresenter
  3. Підклас, ContentControlякщо ви створюєте нестандартний контроль за вмістом хосту, і ви не можете отримати той самий результат, змінивши існуючий шаблон управління (це має бути вкрай рідко).

1
Чи означає це, що, як правило, я, мабуть, повинен використовувати ContentPresenter всередині своїх DataTemplates, тому що це більш легкий вага (але функціонально еквівалентний при використанні в подібному шаблоні DataTemplate)? Тоді просто використовуйте ContentControl як базовий клас, якщо я пишу новий елемент керування?
Вілька

Я відредагував відповідь з більш детальною інформацією про те, коли я буду використовувати ContentPresenter та коли ContentControl
Nir,

1
Гаразд, я зрозумів, що ContentPresenter слід використовувати в шаблонах замість ContentControl, але чому?
sll

32
@sll - ContentControl є базовим класом для кожного елемента управління, який відображає "вміст" (наприклад: Label), ContentPresenter - це код, який використовується ContentControl внутрішньо для відображення вмісту - так: 1. ContentPresenter більш легкий, 2. ContentPresenter призначений для використовуватись всередині шаблонів управління і 3. ContnetPresenter призначений для використання як є, а ContentControl призначений для розширення (успадкованого від)
Nir,

23
ContentPresenter поводиться інакше від ContentControl, коли мова йде про встановлення властивості вмісту. Якщо ви встановите властивість Content Content, то його зміна DataContext буде відповідати властивості вмісту, але DataContext ContentControl залишається незмінним. Це має значення, якщо у вас є інші властивості на ContentPresenter, встановлені через прив'язку, тому що як тільки DataContext змінюється, всі прив'язки використовують це як джерело.
користувач195275

25

ContentPresenter зазвичай використовується в ControlTemplate, як заповнювач, щоб сказати "помістити фактичний вміст сюди".

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


6
Чи не буде ContentPresenter також спричиняти застосування шаблону DataTemplate до його вмісту? Це не є однією з основних цілей?
Дрю Ноакс

1
ммм ... так, певно. Так чи інакше, пояснення Беа Столніц набагато краще, ніж моє;)
Томас Левеск

Ваша лаконічна відповідь, здавалося, підсумовує її швидко: я вважаю, що вся конструкція ContentPresenter полягає в тому, щоб просто "реалізувати" інфляцію DataTemplate --- це, здається, єдина робота - просто знайти та надути шаблон, встановивши також DataContext; і намагаючись потім просто «зникнути» якнайбільше (ТОГО, ЩО ВИ ВИНАГЛИ можна прив’язати всередині надутого шаблону до навколишніх властивостей, таких як властивості TextElement, що надходять потім із ContentPresenter). Не потрібно турбуватися про інші речі, і це просто надуває шаблон порівняно тонко. (Я шукаю найтоншого!)
Стівен Коко,

9

Нещодавно я написав пост у своєму блозі щодо цих двох елементів контролю:

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

ContentPresenter.ContentSource є те , що на насправді робить велику різницю між цими двома класами. Властивість ContentSource має сенс лише у ControlTemplate; він визначає, з якою властивістю TemplatedParent вміст повинен бути відображений. Наприклад, якщо елемент керування містить властивість залежності MyProperty1, то ми можемо виявити таке в його межах ControlTemplate:

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

Вміст ContentPresenter отримає значення MyProperty1.

Зауважте, що якщо назва ресурсу є Content, вказувати не потрібно, ContentSourceоскільки це значення за замовчуванням.

Для тих, хто знає angularJs: це схоже на переключення меканізму.


2

Це старе питання, але я тільки закінчував розробку анімованого керування плиткою, шаблону для універсальної програми, дивіться на цей код зі старого SDK телефону 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, коли розробляли SDK WP7 / 8. ContentControl також може використовуватися для відображення вмісту, але тоді він служить як контейнером, так і презентатором. Тож у зразковому коді вище його призначення розбито на контейнери та презентатори. У динамічних зразках ви можете відобразити контейнер (він може мати порожній фон або щось ще немає), а потім динамічно заповнити його вмістом презентатора. Контейнер має розміри (ширина, висота тощо), ви ставите ці властивості на елемент управління контейнером і представляєте вміст на ньому. У зразку ContentControl визначає, що потрібно робити зі змістом презентатора.


1

Іноді приклад легший, ніж теоретичний жаргон. На веб-сайті 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. ІншийControl розмістить те, що ви вказали, де знаходиться ContentPresenter.

Аналогічно, якщо порівнювати TextBox та TextBlock, TextBox має ContentPresenter для того, щоб ви вміщували в нього речі, як у наведеному вище прикладі Кнопки, тоді як TextBlock - ні. TextBlock дозволяє лише вводити текст.


2
A Buttonне має [ ContentControl] (msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol (v = vs.110) .aspx), він є (успадковується від) ContentControl. Button МаєContentPresenter . Зауважте, що ви можете це робити зі стандартом Button, не потрібно його налаштовувати.
АБО Mapper

Але не пов'язане з цим, ця відповідь не пояснює, чи і чому, замість цього ContentPresenter, A ContentControlне можна було б використовувати так само добре, ControlTemplateщоб відобразити вміст Button. Як такий, він не відповідає на питання.
АБО Mapper
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.