Was ist der Unterschied zwischen ContentControl und ContentPresenter?

208

Ich bin mir nicht sicher, wann ich ContentPresenterstattdessen verwenden soll ContentControl(und umgekehrt). Im Moment benutze ich so ContentControlziemlich die ganze Zeit in meinem DataTemplates. Wann wäre ContentPresentereine bessere Wahl? und warum?

Wilka
quelle

Antworten:

163

ContentControlist eine Basisklasse für Steuerelemente, die andere Elemente enthalten und eine ContentEigenschaft haben (z. B. Button).

ContentPresenter wird in Steuerungsvorlagen verwendet, um Inhalte anzuzeigen.

ContentControlWenn es direkt verwendet wird (es soll als Basisklasse verwendet werden), verfügt es über eine Steuerelementvorlage, die ContentPresenter verwendet, um den Inhalt anzuzeigen.

Meine Faustregeln (nicht in jedem Fall anwendbar, verwenden Sie Ihr Urteilsvermögen):

  1. Innerhalb ControlTemplateEinsatzContentPresenter
  2. Außerhalb von ControlTemplate(einschließlich DataTemplateund außerhalb von Vorlagen) versuchen Sie, keine von ihnen zu verwenden. Wenn Sie dies benötigen, müssen Sie dies vorziehenContentPresenter
  3. Unterklasse, ContentControlwenn Sie ein benutzerdefiniertes "Lookless" -Steuerelement erstellen, das Inhalte hostet, und Sie nicht das gleiche Ergebnis erzielen können, indem Sie die Vorlage eines vorhandenen Steuerelements ändern (dies sollte äußerst selten sein).
Nir
quelle
1
Bedeutet das, dass ich ContentPresenter im Allgemeinen wahrscheinlich in meinen DataTemplates verwenden sollte, da es leichter ist (aber funktional gleichwertig, wenn es in einem DataTemplate wie diesem verwendet wird)? Verwenden Sie dann einfach ContentControl als Basisklasse, wenn ich ein neues Steuerelement schreibe.
Wilka
Ich habe die Antwort mit weiteren Details bearbeitet, wann ich ContentPresenter verwenden würde und wann ContentControl
Nir
1
Ok, ich habe die Idee, dass ContentPresenter in Vorlagen anstelle von ContentControl verwendet werden soll, aber warum?
sll
32
@sll - ContentControl ist die Basisklasse für jedes Steuerelement, das "Inhalt" anzeigt (Beispiel: Label). ContentPresenter ist der Code, der von ContentControl intern zum Anzeigen des Inhalts verwendet wird. Also: 1. ContentPresenter ist leichter, 2. ContentPresenter wurde entwickelt in Steuerungsvorlagen verwendet werden und 3. ContnetPresenter ist so konzipiert, dass es unverändert verwendet wird, während ContentControl erweitert (geerbt von) ist
Nir
23
ContentPresenter verhält sich anders als ContentControl, wenn die Content-Eigenschaft festgelegt wird. Wenn Sie die Content-Eigenschaft von ContentPresenter festlegen, ändert sich der DataContext entsprechend der Content-Eigenschaft, der DataContext von ContentControl bleibt jedoch unberührt. Dies ist wichtig, wenn Sie andere Eigenschaften in ContentPresenter über die Bindung festgelegt haben, da alle Bindungen diese als Quelle verwenden, sobald sich DataContext ändert.
user195275
25

ContentPresenter wird normalerweise in einer ControlTemplate als Platzhalter verwendet, um "den eigentlichen Inhalt hier einfügen" zu sagen.

Ein ContentControl kann überall verwendet werden, nicht unbedingt in einer Vorlage. Es nimmt alle DataTemplate auf, die für den ihm zugewiesenen Inhaltstyp definiert sind

Thomas Levesque
quelle
6
Würde ein ContentPresenter nicht auch dazu führen, dass ein DataTemplate auf seinen Inhalt angewendet wird? Ist das nicht einer seiner Hauptzwecke?
Drew Noakes
1
mmm ... ja, wahrscheinlich. Wie auch immer, Bea Stollnitz 'Erklärung ist viel besser als meine;)
Thomas Levesque
Ihre prägnante Antwort schien es schnell zusammenzufassen: Ich glaube, das gesamte Design des ContentPresenter besteht darin, die DataTemplate-Inflation einfach zu "implementieren" - es scheint die einzige Aufgabe zu haben, nur die Vorlage zu lokalisieren und aufzublasen und auch den DataContext festzulegen. und versuchen Sie dann, so weit wie möglich "zu verschwinden" (obwohl Sie immer noch innerhalb der aufgeblasenen Vorlage an Umgebungseigenschaften wie TextElement-Eigenschaften binden können, die dann vom ContentPresenter stammen). Sie müssen sich nicht um andere Dinge kümmern, und die Vorlage wird nur relativ schlank aufgeblasen. (Ich suche das schlankste!)
Steven Coco
9

Ich habe kürzlich in meinem Blog einen Beitrag zu diesen beiden Steuerelementen geschrieben:

ContentPresenter vs ContentControl ( BEARBEITEN : Defekter Link durch archivierte Version ersetzt.)

Die ContentPresenter.ContentSource macht tatsächlich den größten Unterschied zwischen den beiden Klassen aus. Die ContentSource-Eigenschaft ist nur innerhalb einer ControlTemplate sinnvoll. Es bestimmt, mit welcher TemplatedParent-Eigenschaft der Inhalt zugeordnet werden soll. Wenn ein Steuerelement beispielsweise eine Abhängigkeitseigenschaft enthält MyProperty1, finden Sie möglicherweise Folgendes in seiner ControlTemplate:

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

Der Inhalt des ContentPresenter erhält den Wert von MyProperty1.

Bitte beachten Sie, dass bei einem Namen der Eigenschaft Contentkeine Angabe erforderlich ist, ContentSourceda dies der Standardwert ist.

Für diejenigen, die eckige Js kennen: Dies ist ähnlich wie das Ausschließen von Mekanismus.

Charles HETIER
quelle
2

Es ist eine alte Frage, aber ich habe gerade die Entwicklung einer animierten Kachelsteuerung abgeschlossen, einer Vorlage, die auf einer universellen App basiert. Sehen Sie sich diesen Code aus dem alten Phone WP7 / 8 SDK an:

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

Hier sehen Sie, dass ContentControl der Container und der Präsentator für die Anzeige von Inhalten ist. In den meisten Fällen ist die ControlTemplate der Container. Wenn Sie jedoch in ControlTemplateeinem anderen Container möchten , können Sie einen zusätzlichen Container einfügen: ContentControldarin und für die Darstellung des Inhalts einen separaten ContentPresenter. Wenn Sie keinen separaten Container benötigen, verwenden Sie einfach ControlTemplateundControlPresentersZumindest für die Anzeige von Inhaltsblöcken haben die Mitarbeiter von Microsoft das WP7 / 8 SDK entwickelt. Das ContentControl kann auch zum Anzeigen von Inhalten verwendet werden, dient dann aber sowohl als Container als auch als Präsentator. Im obigen Beispielcode wird sein Zweck in Container und Presenter aufgeteilt. In dynamischen Beispielen können Sie den Container anzeigen (er kann einen leeren Hintergrund haben oder etwas, das noch nicht vorhanden ist) und ihn dann dynamisch mit dem Inhalt des Präsentators füllen. Ein Container hat Abmessungen (Breite, Höhe usw.). Sie fügen diese Eigenschaften dem Containersteuerelement hinzu und präsentieren den Inhalt darauf. Im Beispiel bestimmt das ContentControl, was mit dem Präsentatorinhalt zu tun ist.

Herman Van Der Blom
quelle
1

Manchmal ist ein Beispiel einfacher als theoretischer Jargon. Auf einer MS-Website (Scrollen Sie nach unten: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx ) wird eine Schaltfläche als verwendet ein Beispiel. Eine Schaltfläche verfügt über ein ContentControl, mit dem Sie ein Steuerelement oder ein benutzerdefiniertes Steuerelement platzieren können, bei dem es sich um ein Bild, einen Text, eine CheckBox, ein StackPanel, ein Raster usw. handeln kann.

Nach der Anpassung von Button können Sie jetzt auf der Xaml schreiben

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

Im obigen Beispielcode ist "my: Button.Content" das ContentControl. Das AnotherControl befindet sich an der Stelle, an der sich der ContentPresenter befindet.

Wenn Sie TextBox und TextBlock vergleichen, verfügt TextBox über einen ContentPresenter, mit dem Sie Inhalte wie im obigen Button-Beispiel einfügen können, während dies bei einem TextBlock nicht der Fall ist. Mit einem TextBlock können Sie nur Text eingeben.

Wayne Lo
quelle
2
A Buttonnicht haben eine [ ContentControl] (msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol (v = vs.110) aspx), es ist ein (erbt von) ContentControl. Das Button hat eine ContentPresenter. Beachten Sie, dass Sie dies mit dem Standard tun können Button, ohne ihn anpassen zu müssen.
ODER Mapper
Unabhängig davon erklärt diese Antwort jedoch nicht, ob und warum a anstelle von ContentPresentera ContentControlnicht genauso gut ControlTemplatezur Anzeige des Inhalts von verwendet werden konnte Button. Als solches beantwortet es die Frage nicht.
ODER Mapper