Jaka jest różnica między ContentControl a ContentPresenter?

208

Nie jestem pewien, kiedy powinienem użyć ContentPresenterzamiast ContentControl(i odwrotnie). W tej chwili używam ContentControlprawie cały czas w moim DataTemplate. Kiedy byłby ContentPresenterlepszy wybór? i dlaczego?

Wilka
źródło

Odpowiedzi:

164

ContentControljest klasą bazową dla kontrolek, które zawierają inne elementy i mają Contentwłaściwość (na przykład Button).

ContentPresenter jest używany w szablonach kontrolnych do wyświetlania treści.

ContentControl, gdy jest używany bezpośrednio (ma być używany jako klasa podstawowa), ma szablon kontrolny, który używa ContentPresenter do wyświetlania jego zawartości.

Moje ogólne zasady (nie dotyczy wszystkich przypadków, skorzystaj z własnego osądu):

  1. ControlTemplateZastosowanie wewnętrzneContentPresenter
  2. Poza szablonami ControlTemplate(w tym DataTemplatei zewnętrznymi) staraj się nie używać żadnego z nich, jeśli musisz, musisz to zrobićContentPresenter
  3. Podklasę, ContentControljeśli tworzysz niestandardową „nie wyglądającą” kontrolkę, która hostuje zawartość i nie możesz uzyskać tego samego wyniku, zmieniając szablon istniejącej kontrolki (co powinno być niezwykle rzadkie).
Nir
źródło
1
Czy to oznacza, że ​​ogólnie powinienem prawdopodobnie używać ContentPresenter wewnątrz moich DataTemplates, ponieważ jest on bardziej lekki (ale funkcjonalnie równoważny, gdy jest używany w takim DataTemplate)? Więc użyj ContentControl jako klasy bazowej, jeśli piszę nową kontrolkę?
Wilka,
Zredagowałem odpowiedź z bardziej szczegółowymi informacjami, kiedy chciałbym użyć ContentPresenter, a kiedy ContentControl
Nir,
1
Ok, mam pomysł, że ContentPresenter powinien być używany w szablonach zamiast ContentControl, ale dlaczego?
sll
32
@sll - ContentControl jest klasą podstawową dla każdej kontrolki wyświetlającej „treść” (przykład: Etykieta), ContentPresenter to kod używany wewnętrznie przez ContentControl do wyświetlania treści - więc: 1. ContentPresenter jest bardziej lekki, 2. ContentPresenter jest zaprojektowany do być używane w szablonach kontrolnych i 3. ContnetPresenter jest przeznaczony do użycia w stanie, w jakim się znajduje, podczas gdy ContentControl jest przeznaczony do rozszerzenia (odziedziczony z)
Nir
23
ContentPresenter zachowuje się inaczej niż ContentControl, jeśli chodzi o ustawienie właściwości Content. Gdy ustawisz właściwość ContentPresenter Content, jej DataContext zmieni się, aby pasować do właściwości Content, ale DataContext ContentControl pozostaje niezmieniony. Ma to znaczenie, jeśli masz inne właściwości ContentPresenter ustawione za pomocą wiązania, ponieważ po zmianie DataContext wszystkie powiązania wykorzystują to jako źródło.
user195275,
25

ContentPresenter jest zwykle używany w ControlTemplate, jako symbol zastępczy, który mówi „umieść tutaj rzeczywistą treść”.

ContentControl może być używany w dowolnym miejscu, niekoniecznie w szablonie. Wybiera dowolny DataTemplate zdefiniowany dla typu przypisanej mu treści

Thomas Levesque
źródło
6
Czy ContentPresenter nie spowodowałby również zastosowania DataTemplate do jego zawartości? Czy to nie jeden z głównych celów?
Drew Noakes,
1
mmm ... tak, prawdopodobnie. W każdym razie wyjaśnienie Bei Stollnitz jest znacznie lepsze niż moje;)
Thomas Levesque
Twoja zwięzła odpowiedź zdawała się szybko podsumowywać: uważam, że cały projekt ContentPresenter polega po prostu na „wdrożeniu” inflacji DataTemplate - wydaje się, że jedynym zadaniem jest po prostu zlokalizowanie i zawyżenie szablonu, ustawienie DataContext; i wtedy staramy się po prostu „zniknąć” tak bardzo, jak to możliwe (TYM NADAL MOŻESZ wiązać wewnątrz napompowanego szablonu z właściwościami otoczenia, takimi jak właściwości TextElement, pochodzącymi wówczas z ContentPresenter). Nie musisz się martwić o inne rzeczy, a to tylko napełnia szablon w stosunkowo wąski sposób. (Szukam najcieńszego!)
Steven Coco,
9

Niedawno napisałem na moim blogu post dotyczący tych dwóch elementów sterujących:

ContentPresenter vs ContentControl (EDYCJA: Uszkodzony link zastąpiony wersją zarchiwizowaną).

ContentPresenter.ContentSource to co rzeczywiście sprawia, że największa różnica między tymi dwoma klasami. Właściwość ContentSource ma sens tylko w obrębie ControlTemplate; określa, z której właściwości TemplatedParent należy mapować treść. Na przykład, jeśli formant zawiera właściwość zależności MyProperty1, wówczas możemy znaleźć następujące elementy ControlTemplate:

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

Zawartość ContentPresenter otrzyma wartość MyProperty1.

Należy pamiętać, że jeśli nazwa właściwości to Content, nie trzeba jej określać, ContentSourceponieważ jest to wartość domyślna.

Dla tych, którzy znają angularJs: jest to podobne do przełamywania mechanizmu.

Charles HETIER
źródło
2

To stare pytanie, ale właśnie kończyłem opracowywanie animowanego Tile Control, szablonu opartego na uniwersalnej aplikacji, spójrz na ten kod ze starego SDK telefonu WP7 / 8:

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

Tutaj możesz zobaczyć, że ContentControl jest kontenerem i prezenterem do wyświetlania treści. W większości przypadków ControlTemplate będzie kontenerem, ale jeśli chcesz w ControlTemplateinnym kontenerze, możesz umieścić dodatkowy kontener: ContentControlw nim i do prezentacji zawartości osobnyContentPresenter . Jeśli nie potrzebujesz osobnego pojemnika, po prostu użyj ControlTemplateiControlPresentersdo wyświetlania bloków treści przynajmniej tak zrobili faceci z Microsoftu, kiedy opracowali pakiet SDK WP7 / 8. ContentControl może również służyć do wyświetlania treści, ale służy jednocześnie jako kontener i prezenter. Tak więc w powyższym przykładowym kodzie jego przeznaczenie jest podzielone na kontener i prezenter. W próbkach dynamicznych możesz wyświetlić kontener (może mieć puste tło lub coś, czego jeszcze tam nie ma), a następnie dynamicznie wypełnić go treścią prezentera. Kontener ma wymiary (szerokość, wysokość itp.), Umieszczasz te właściwości w kontrolce kontenera i wyświetlasz na nim zawartość. W przykładzie ContentControl określa, co należy zrobić z treścią prezentera.

Herman Van Der Blom
źródło
1

Czasami przykład jest łatwiejszy niż teoretyczny żargon. W witrynie MS (przewiń w dół: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx ) używa przycisku jako przykład. Button ma kontrolkę ContentControl, która pozwala umieścić jedną kontrolkę lub kontrolkę niestandardową, która może być obrazem, tekstem, CheckBox, StackPanel, siatką, cokolwiek.

Po dostosowaniu przycisku, teraz na Xaml, możesz pisać

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

W powyższym przykładowym kodzie „my: Button.Content” to ContentControl. AnotherControl będzie miejscem, które podałeś, gdzie jest ContentPresenter.

Podobnie, gdy porównuje się TextBox i TextBlock, TextBox ma ContentPresenter, abyś mógł w nim umieszczać rzeczy, tak jak w powyższym przykładzie przycisku, podczas gdy TextBlock nie. TextBlock pozwala tylko na wprowadzanie tekstu.

Wayne Lo
źródło
2
A Buttonnie ma [ ContentControl] (msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol (v = vs.110) .aspx), to jest (dziedziczy z) ContentControl. Button MaContentPresenter . Pamiętaj, że możesz to zrobić za pomocą standardu Button, nie musisz go dostosowywać.
LUB Mapper
Ale niezwiązana z tym, ta odpowiedź nie wyjaśnia, czy i dlaczego zamiast ContentPresentera ContentControlnie można było użyć równie dobrze w ControlTemplatecelu wyświetlenia zawartości Button. Jako taki nie odpowiada na pytanie.
LUB Mapper