¿Cuál es la diferencia entre ContentControl y ContentPresenter?

No estoy seguro de cuándo debería usar ContentPresenter lugar de ContentControl (y viceversa). Por el momento, estoy usando ContentControl casi todo el tiempo en mi DataTemplate s. ¿Cuándo sería ContentPresenter una mejor opción? ¿y por qué?

ContentControl es una clase base para los controles que contienen otros elementos y tienen una propiedad Content (por ejemplo, Button ).

ContentPresenter se usa dentro de plantillas de control para mostrar contenido.

ContentControl , cuando se usa directamente (se supone que debe usarse como una clase base), tiene una plantilla de control que usa ContentPresenter para mostrar su contenido.

Mis reglas generales (no aplicable en todos los casos, use su criterio):

  1. Dentro de ControlTemplate usa ContentPresenter
  2. Fuera de ControlTemplate (incluyendo DataTemplate y plantillas externas) intente no usar ninguno de ellos, si es necesario, debe preferir ContentPresenter
  3. Haga una subclase de ContentControl si está creando un control “sin aspecto” personalizado que aloja el contenido y no puede obtener el mismo resultado cambiando la plantilla de un control existente (que debería ser extremadamente raro).

ContentPresenter generalmente se usa en ControlTemplate, como marcador de posición para decir “poner aquí el contenido real”.

Un ContentControl se puede usar en cualquier lugar, no necesariamente en una plantilla. Recogerá cualquier DataTemplate definido para el tipo de contenido asignado a él

Recientemente escribí una publicación en mi blog con respecto a estos dos controles:

ContentPresenter vs ContentControl (EDITAR: Enlace roto reemplazado por versión archivada)

ContentPresenter.ContentSource es lo que realmente marca la mayor diferencia entre las dos clases. La propiedad ContentSource tiene sentido solo dentro de ControlTemplate; determina con qué propiedad de TemplatedParent debe correlacionarse el contenido. Por ejemplo, si un control contiene una propiedad de dependencia MyProperty1 , entonces podríamos encontrar lo siguiente dentro de su ControlTemplate :

  [...]  [...]  

El contenido de ContentPresenter recibirá el valor de MyProperty1 .

Tenga en cuenta que si el nombre de la propiedad es Content , no es necesario especificar ContentSource ya que es el valor predeterminado.

Para aquellos que conocen angularJs: esto es similar al mecanismo de transcluir.

A veces, un ejemplo es más fácil que la jerga teórica. En un sitio web de MS (Desplácese hasta la parte inferior: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx ), usa un botón como un ejemplo. Un botón tiene un control de contenido, que le permite colocar un control o un control personalizado que podría ser una imagen, texto, checkbox, panel de stack, cuadrícula, lo que sea.

Después de la personalización de Button, ahora en Xaml, puedes escribir

      

En el código de ejemplo anterior, el “my: Button.Content” es ContentControl. El AnotherControl se colocará según lo que usted especificó donde está el ContentPresenter.

Del mismo modo, cuando se compara TextBox y TextBlock, TextBox tiene un ContentPresenter para que puedas meter cosas en él igual que el ejemplo de Button anterior, mientras que TextBlock no lo hace. Un TextBlock solo le permite ingresar texto.

Es una vieja pregunta, pero estaba terminando de desarrollar una plantilla animada de control de mosaico, basada en una aplicación universal, mira este código del antiguo Phone WP7 / 8 SDK:

    

Aquí puede ver que ContentControl es el contenedor y el presentador para mostrar contenido. En la mayoría de los casos, el ControlTemplate será el Contenedor, pero si desea en su ControlTemplate otro contenedor, puede colocar un Contenedor adicional: ContentControl en él y, para presentar el contenido, un ContentPresenter separado. Si no necesita un contenedor por separado, simplemente use ControlTemplate y ControlPresenters para mostrar los bloques de contenido, al menos eso es lo que hicieron los chicos de Microsoft cuando desarrollaron el WP7 / 8 SDK. ContentControl también se puede usar para mostrar contenido pero luego sirve como contenedor y presentador. Por lo tanto, en el código de ejemplo anterior, su propósito se divide en Container y Presenter. En las muestras dinámicas, puede visualizar el contenedor (puede tener un fondo vacío o algo que aún no está allí) y luego llenarlo dinámicamente con el contenido del presentador. Un contenedor tiene dimensiones (ancho, alto, etc.), coloca esas propiedades en el control del contenedor y presenta contenido en él. En la muestra, ContentControl determina qué se debe hacer con el contenido del presentador.