Compartir a través de


Aplicar estilos y plantillas

Actualización: noviembre 2007

Los estilos y plantillas de Windows Presentation Foundation (WPF) hacen referencia a un conjunto de características (estilos, plantillas, desencadenadores y guiones gráficos) que permiten a los diseñadores de una aplicación, documento o interfaz de usuario (UI) crear efectos visualmente atractivos y estandarizar de manera coherente la apariencia del producto. Aunque un autor o diseñador puede personalizar ampliamente la apariencia de las aplicaciones una por una, se necesita un modelo robusto de estilos y plantillas para permitir el mantenimiento y el uso compartido de la apariencia tanto dentro de una aplicación como entre las diversas aplicaciones. Windows Presentation Foundation (WPF) proporciona ese modelo.

Otra característica del modelo de estilos de WPF es la separación de la presentación y la lógica. Esto significa que los diseñadores pueden trabajar en la apariencia de una aplicación utilizando solamente XAML, al mismo tiempo que los desarrolladores trabajan en la lógica de programación utilizando C# o Visual Basic.

En esta información general se explica la aplicación Ejemplo Introduction to Styling and Templating, que tiene dos elementos TextBlock y un control ListBox enlazado a una lista de imágenes:

ListView con estilo

Esta información general se centra en los aspectos de estilos y plantillas de la aplicación y no aborda los conceptos de enlace de datos. Para obtener información sobre el enlace de datos, vea Información general sobre el enlace de datos.

Además, es importante entender los recursos, que permiten reutilizar los estilos y las plantillas. Para obtener más información sobre los recursos, vea Información general sobre recursos.

Este tema contiene las secciones siguientes.

  • Fundamentos de estilos
  • Plantillas de datos
  • Plantillas de control
  • Desencadenadores
  • Recursos y temas compartidos
  • Temas relacionados

Fundamentos de estilos

Puede considerar un objeto Style como una manera cómoda de aplicar un conjunto de valores de propiedades a más de un elemento. Por ejemplo, considere los siguientes elementos TextBlock y su apariencia predeterminada:

<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

Captura de pantalla de ejemplo de aplicación de estilos

Puede cambiar la apariencia predeterminada estableciendo directamente propiedades como FontSize y FontFamily en cada elemento TextBlock. Sin embargo, si desea que los elementos TextBlock compartan algunas propiedades, puede crear un objeto Style en la sección Resources del archivo XAML, como se muestra aquí:

<Window.Resources>


...


<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
  <Setter Property="HorizontalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
  <Setter Property="FontSize" Value="14"/>
</Style>


...


</Window.Resources>

Cuando establezca la propiedad TargetType del estilo en el tipo TextBlock, el estilo se aplicará a todos los elementos TextBlock de la ventana.

Ahora, los elementos TextBlock aparecerán de la manera siguiente:

Captura de pantalla de ejemplo de aplicación de estilos

Este tema contiene las subsecciones siguientes.

  • Extender los estilos
  • Relación entre la propiedad TargetType y el atributo x:Key
  • Estilos y recursos
  • Establecer estilos mediante programación
  • Enlaces, recursos dinámicos y controladores de eventos

Extender los estilos

Quizás desee que los dos elementos TextBlock compartan algunos valores de propiedad, como FontFamily y un valor de HorizontalAlignment centrado, pero también desee que el texto "My Pictures" tenga algunas propiedades adicionales. Para ello, cree un nuevo estilo basado en el primer estilo, como se muestra aquí:

<Window.Resources>


...


<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
       TargetType="TextBlock"
       x:Key="TitleText">
  <Setter Property="FontSize" Value="26"/>
  <Setter Property="Foreground">
  <Setter.Value>
      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Offset="0.0" Color="#90DDDD" />
          <GradientStop Offset="1.0" Color="#5BFFFF" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
</Style>


...


</Window.Resources>

Observe que al estilo anterior se le asigna un atributo x:Key. Para aplicar el estilo, establezca la propiedad Style del elemento TextBlock en el valor de x:Key, como se muestra aquí:

<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

El estilo de este elemento TextBlock tiene ahora el valor de la propiedad HorizontalAlignment establecido en Center, el valor de la propiedad FontFamily establecido en Comic Sans MS, el valor de la propiedad FontSize establecido en 26 y el valor de la propiedad Foreground establecido en el objeto LinearGradientBrush que se muestra en el ejemplo. Observe que hemos invalidado el valor de FontSize del estilo base. Si hay más de un objeto Setter que establezca la misma propiedad de Style, el objeto Setter que se declare en último lugar tendrá prioridad.

A continuación se muestra la apariencia que tendrán los elementos TextBlock:

TextBlocks con estilo

Este estilo TitleText extiende el estilo creado para el tipo TextBlock. También puede extender un estilo que tenga un atributo x:Key utilizando el valor de x:Key. Para ver un ejemplo, vea el que se proporciona para la propiedad BasedOn.

Relación entre la propiedad TargetType y el atributo x:Key

Como se muestra en el primer ejemplo, si se establece la propiedad TargetType en TextBlock sin asignar al estilo un atributo x:Key, el estilo se aplicará a todos los elementos TextBlock. En este caso, el atributo x:Key se establece implícitamente en {x:Type TextBlock}. Esto significa que si se establece explícitamente el atributo x:Key en un valor que no sea {x:Type TextBlock}, el objeto Style no se aplicará automáticamente a todos los elementos TextBlock. Es preciso aplicar explícitamente el estilo (utilizando el valor de x:Key) a los elementos TextBlock. Si el estilo está en la sección de recursos y no se establece la propiedad TargetType del estilo, se deberá proporcionar un atributo x:Key.

Además de proporcionar un valor predeterminado para x:Key, la propiedad TargetType especifica el tipo al que se aplican las propiedades del establecedor. Si no se especifica un valor de TargetType, se deberán certificar las propiedades de los objetos Setter con un nombre de clase, utilizando la sintaxis Property="ClassName.Property". Por ejemplo, en lugar de establecer Property="FontSize", se deberá establecer Property en "TextBlock.FontSize" o "Control.FontSize".

Observe también que muchos controles de WPF son una combinación de otros controles de WPF. Si crea un estilo que se aplique a todos los controles de un tipo, puede que obtenga resultados inesperados. Por ejemplo, si crea un estilo cuyo objetivo sea el tipo de TextBlock en un objeto Window, el estilo se aplicará a todos los controles TextBlock de la ventana, aunque el elemento TextBlock forme parte de otro control, como un control ListBox.

Estilos y recursos

Puede utilizar un estilo en cualquier elemento que derive de FrameworkElement o FrameworkContentElement. La manera más común de declarar un estilo es declararlo como un recurso en la sección Resources de un archivo XAML, como se muestra en los ejemplos anteriores. Dado que los estilos son recursos, siguen las mismas reglas de ámbito que se aplican a todos los recursos; la ubicación donde se declara un estilo afecta a la parte donde se puede aplicar. Por ejemplo, si se declara el estilo en el elemento raíz del archivo XAML de definición de la aplicación, el estilo se puede usar en cualquier parte de la aplicación. Si se crea una aplicación de navegación y se declara el estilo en uno de sus archivos XAML, el estilo sólo se puede usar en ese archivo XAML. Para obtener más información sobre las reglas de ámbito para los recursos, vea Información general sobre recursos.

Además, hay más información sobre los estilos y recursos en la sección Recursos y temas compartidos, más adelante en esta información general.

Establecer estilos mediante programación

Para asignar mediante programación un estilo con nombre a un elemento, obtenga el estilo de la colección de recursos y asígnelo a la propiedad Style del elemento. Observe que los elementos de una colección de recursos son de tipo Object, de modo que debe convertir el estilo recuperado en un objeto Style antes de asignarlo a la propiedad Style. Por ejemplo, para establecer el estilo TitleText definido de un control TextBlock denominado textblock1, siga este procedimiento:

textblock1.Style = (Style)(this.Resources["TitleText"]);

Tenga en cuenta que, una vez aplicado un estilo, éste queda sellado y no puede cambiarse. Si desea cambiar dinámicamente un estilo que ya se ha aplicado, deberá crear un nuevo estilo para reemplazar el existente. Para obtener más información, vea la propiedad IsSealed.

Puede crear un objeto que elija el estilo que se va a aplicar basándose en una lógica personalizada. Para obtener un ejemplo, vea el que se proporciona para la clase StyleSelector.

Enlaces, recursos dinámicos y controladores de eventos

Observe que puede usar la propiedad Setter.Value para especificar una Enlazar extensión de marcado o una Extensión de marcado DynamicResource. Para obtener más información, vea los ejemplos proporcionados para la propiedad Setter.Value.

Hasta ahora, hemos explicado solamente el uso de establecedores para establecer el valor de la propiedad. En un estilo, también se pueden especificar los controladores de eventos. Para obtener más información, vea EventSetter.

Plantillas de datos

En esta aplicación de ejemplo, hay un control ListBox enlazado a una lista de fotos:

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
         Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>

Este control ListBox tiene ahora la siguiente apariencia:

ListBox antes de aplicar una plantilla

La mayoría de los controles tienen algún tipo de contenido y ese contenido suele proceder de los datos a los que se está enlazando. En este ejemplo, los datos son la lista de fotos. En WPF, utilice DataTemplate para definir la representación visual de los datos. Básicamente, el contenido de DataTemplate determina la apariencia de los datos en la aplicación representada.

En la aplicación de ejemplo, cada objeto Photo personalizado tiene una propiedad Source de tipo cadena que especifica la ruta de acceso del archivo de imagen. Actualmente, los objetos de foto aparecen como rutas de acceso de archivo.

Para que las fotos aparezcan como imágenes, debe crear un objeto DataTemplate como un recurso:

<Window.Resources>


...


<!--DataTemplate to display Photos as images
    instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
  <Border Margin="3">
    <Image Source="{Binding Source}"/>
  </Border>
</DataTemplate>


...


</Window.Resources>

Observe que la propiedad DataType es muy similar a la propiedad TargetType de Style. Si DataTemplate está en la sección de recursos, al especificar la propiedad DataType en un tipo y no asignarle un atributo x:Key, DataTemplate se aplicará cada vez que aparezca ese tipo. Siempre tiene la opción de asignar a DataTemplate un atributo x:Key y, a continuación, establecerlo como StaticResource para las propiedades que admiten tipos DataTemplate, como la propiedad ItemTemplate o la propiedad ContentTemplate.

El objeto DataTemplate del ejemplo anterior define esencialmente que, siempre que haya un objeto Photo, éste debe aparecer como un control Image dentro de un control Border. Con este objeto DataTemplate, la aplicación tiene ahora esta apariencia:

Imagen fotográfica

El modelo de plantillas de datos proporciona otras características. Por ejemplo, si se muestran datos de colección que contengan otras colecciones con un tipo HeaderedItemsControl como un control Menu o un control TreeView, ahí está el objeto HierarchicalDataTemplate. Otra característica de las plantillas de datos es el objeto DataTemplateSelector, que permite elegir el objeto DataTemplate que se va a utilizar basándose en una lógica personalizada. Para obtener más información, vea Información general sobre plantillas de datos, que ofrece una explicación más detallada de las diferentes características de las plantillas de datos.

Plantillas de control

Este tema contiene las subsecciones siguientes.

  • Sin utilizar ControlTemplate
  • ¿Qué es ControlTemplate?
  • Crear un objeto ControlTemplate
  • Propiedad IsItemsHost
  • ItemsPresenter y ContentPresenter
  • TemplateBinding

Ahora que las fotos aparecen como imágenes, vamos a mostrarlas horizontalmente en lugar de verticalmente; el control ListBox se va a mostrar horizontalmente.

Sin utilizar ControlTemplate

En primer lugar, es importante señalar que no es necesario utilizar el objeto ControlTemplate para que el control ListBox sea horizontal. ListBox tiene la propiedad ItemsPanel, que permite establecer un objeto ItemsPanelTemplate, la plantilla que controla el diseño de los elementos del control ListBox. Una opción es crear simplemente un estilo de ListBox y establecer la propiedad ItemsPanel, como en el ejemplo siguiente:

<Style TargetType="ListBox">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"/>
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

Este procedimiento funciona bien y el resultado es un control ListBox horizontal. En este ejemplo se muestra que, dependiendo del escenario, puede haber otras opciones además de reemplazar el objeto ControlTemplate. Para este ejemplo, si deseamos obtener un control ListBox horizontal que tenga propiedades adicionales, como esquinas redondeadas, necesitamos trabajar con el objeto ControlTemplate del control ListBox.

Antes de proporcionar un ejemplo para mostrar cómo hacerlo, es importante explicar primero el concepto de ControlTemplate.

¿Qué es ControlTemplate?

La mayoría de controles tienen una apariencia y un comportamiento. Considere un botón: la apariencia es el área elevada que se puede presionar y el comportamiento es el evento Click que se provoca en respuesta a un clic.

En ocasiones, puede haber un control que proporcione el comportamiento necesario, pero no la apariencia necesaria. Hasta ahora, hemos mostrado que puede utilizar establecedores de estilo para establecer valores de propiedad que afecten a la apariencia del control. Sin embargo, para cambiar la estructura de un control o establecer valores de propiedad en los componentes de un control, debe utilizar un objeto ControlTemplate.

En WPF, el objeto ControlTemplate de un control define su apariencia. Puede cambiar la estructura y la apariencia de un control definiendo un nuevo objeto ControlTemplate para el control. En muchos casos, esto ofrece suficiente flexibilidad como para no tener que escribir controles personalizados. Si no define un objeto ControlTemplate propio para el control, debe obtener la plantilla predeterminada que se ajuste al tema del sistema; es esta plantilla la que da la apariencia predeterminada al control Button.

Recuerde que al crear un objeto ControlTemplate para el control, se reemplaza el objeto ControlTemplate completo. Por ejemplo, puede definir el objeto ControlTemplate de un control Button de la manera siguiente.

Observe que el elemento ContentPresenter simplemente marca dónde debe ir la propiedad Content del control Button. Explicaremos las diferentes partes en una sección posterior.

<Style TargetType="Button">
  <!--Set to true to not get any properties from the themes.-->
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse Fill="{TemplateBinding Background}"/>
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Una vez aplicado, el control Button aparece como Ellipse:

Ejemplo de ControlTemplate de Button

Recuerde que la apariencia que presenta el control Button cuando tiene el foco o está presionado forma parte de la apariencia predeterminada del botón que está reemplazando. Por consiguiente, en función de sus necesidades, quizá desee incluir en la definición la apariencia que debe tener el botón cuando está presionado. Para obtener un ejemplo completo, vea Ejemplo de ControlTemplate de Button.

Cuando cree un objeto ControlTemplate, la mejor manera de empezar es utilizar los Ejemplos de ControlTemplate. Si realmente necesita examinar las partes de las que se compone un control, puede echar una mirada al archivo de temas ubicado en Temas o puede utilizar la funcionalidad Show Visual Tree de XAMLPad, una aplicación que se instala con Kit de desarrollo de software de Windows (SDK).

Crear un objeto ControlTemplate

Ahora, vamos a continuar con nuestro ejemplo y crear un objeto ControlTemplate que defina un control ListBox horizontal y con esquinas redondeadas. Para reemplazar el objeto ControlTemplate de un control, establezca la propiedad Template en el nuevo objeto ControlTemplate.

<Style TargetType="ListBox">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBox">
        <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
          <ScrollViewer HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Cuando se establece la propiedad Template de esta manera, no hay realmente ninguna diferencia con el establecimiento de otras propiedades de control mediante Style: se usa un objeto Style como una herramienta que ayuda a establecer la propiedad Template. Esto significa que otra manera de establecer un objeto ControlTemplate es establecer directamente la propiedad Template en el control. Si procede de esta manera, crea un objeto ControlTemplate en la sección Resources, le asigna un atributo x:Key y, a continuación, lo utiliza como un recurso estático. Para obtener un ejemplo, vea la propiedad Template.

Como puede ver en el ejemplo anterior, la clase ControlTemplate tiene una propiedad TargetType que es similar a la propiedad TargetType de la clase Style. No obstante, observe que, a diferencia de Style y DataTemplate, los objetos ControlTemplate no tienen la noción de una clave implícita. En otras palabras, si tiene un objeto ControlTemplate independiente con la propiedad TargetType establecida en un tipo, el objeto ControlTemplate no se aplicará automáticamente a ese tipo. Observe también que se requiere la propiedad TargetType en un objeto ControlTemplate si la definición de la plantilla contiene un objeto ContentPresenter.

Experimente con el objeto ControlTemplate. Por ejemplo, reemplace el control StackPanel con un control WrapPanel, establezca la propiedad HorizontalScrollBarVisibility del control ScrollViewer en Disabled y, a continuación, establezca el ancho del control ListBox en 300. (WrapPanel solamente coloca elementos en la fila siguiente cuando la primera fila se queda sin espacio. Si no establece la propiedad HorizontalScrollBarVisibility del control ScrollViewer en Disabled, la primera fila no se queda sin espacio porque es posible desplazarse hasta el final. Como resultado, el control WrapPanel no ajusta los elementos.)

Propiedad IsItemsHost

En este ejemplo, una propiedad importante que debe estar presente es la propiedad IsItemsHost. La propiedad IsItemsHost se utiliza para indicar en la plantilla de un control ItemsControl (controles como ListBox que tienen una lista de elementos) dónde deben ir los elementos generados. Si se establece la propiedad en true en el control StackPanel, cualquier elemento que se agregue al control ListBox se incluirá en el control StackPanel. Observe que esta propiedad solamente funciona en los tipos Panel.

ItemsPresenter y ContentPresenter

Sin embargo, observe que al especificar un panel en ControlTemplate y marcarlo como IsItemsHost de esta manera, el usuario del control no puede reemplazar ItemsPanel sin utilizar un objeto ControlTemplate. Por consiguiente, proceda solamente de esta manera si sabe con seguridad que no desea reemplazar el panel sin usar una plantilla. También puede utilizar el elemento ItemsPresenter para marcar dónde deben ir los elementos y, a continuación, especificar un objeto ItemsPanelTemplate estableciendo la propiedad ItemsPanel. La página ItemsPanelTemplate incluye un ejemplo en el que se muestra cómo hacerlo. Para obtener otro ejemplo en el que se utiliza el objeto ItemsPresenter, vea Ejemplo de ControlTemplate de TreeView.

Si crea una plantilla para un control ContentControl, como Button, el elemento correspondiente es el control ContentPresenter. De manera similar, coloque este elemento en el objeto ControlTemplate del tipo ContentControl para indicar dónde debe mostrarse el contenido, tal como se indica en el ejemplo de la sección ¿Qué es ControlTemplate? Para obtener otros ejemplos, vea Ejemplo de ControlTemplate de Label y Ejemplo de ControlTemplate de ListBoxItem.

TemplateBinding

Cabe observar asimismo que en el ejemplo anterior el valor de Background se establece en {TemplateBinding ListBox.Background}. De esta forma, se indica simplemente que el valor de la propiedad Background de Border debe sincronizarse con el valor de Background establecido en el control ListBox. TemplateBinding es similar a Binding. De hecho, TemplateBinding es más eficaz pero menos funcional que Binding; utilizar TemplateBinding es equivalente a utilizar Binding con la propiedad Source establecida en RelativeSource.TemplatedParent.

Utilice TemplateBinding en ControlTemplate cuando desee que el usuario del control controle los valores de determinadas propiedades. TemplateBinding es una extensión de marcado representada por la clase TemplateBindingExtension.

Quizá haya observado que DataTemplate y ControlTemplate son similares en tanto que su contenido se convierte en la visualización de un objeto. Con la definición de ControlTemplate del control ListBox, la aplicación tiene ahora la siguiente apariencia:

Captura de pantalla de ejemplo de aplicación de estilos

Desencadenadores

Style, ControlTemplate y DataTemplate tienen una propiedad Triggers que puede contener un conjunto de desencadenadores. Un desencadenador establece propiedades o inicia acciones, como animaciones, cuando cambia un valor de propiedad o cuando se provoca un evento.

Este tema contiene las subsecciones siguientes.

  • Desencadenadores de propiedades
  • Desencadenadores de eventos y guiones gráficos
  • MultiTrigger, DataTrigger y MultiDataTrigger

Desencadenadores de propiedades

Para mostrar cómo se utilizan los desencadenadores para establecer propiedades, hagamos que cada elemento ListBoxItem sea parcialmente transparente a menos que esté seleccionado.

El estilo siguiente establece el valor de la propiedad Opacity de un elemento ListBoxItem en 0.5. Cuando el valor de la propiedad IsSelected es true, sin embargo, el valor de Opacity se establece en 1.0:

<Style TargetType="ListBoxItem">
  <Setter Property="Opacity" Value="0.5" />
  <Setter Property="MaxHeight" Value="75" />
  <Style.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Setter Property="Opacity" Value="1.0" />
    </Trigger>


...


  </Style.Triggers>
</Style>

En este ejemplo se utiliza una clase Trigger para establecer un valor de propiedad, pero observe que la clase Trigger también tiene las propiedades EnterActions y ExitActions que permiten a un desencadenador realizar acciones.

Observe que también hemos establecido la propiedad MaxHeight del elemento ListBoxItem en 75. En la captura de pantalla siguiente, el tercer elemento es el elemento seleccionado:

ListView con estilo

Desencadenadores de eventos y guiones gráficos

Acabamos de mostrar que un objeto Trigger establece valores de propiedad o inicia acciones en función del valor de una propiedad. Otro tipo de desencadenador es EventTrigger, que inicia un conjunto de acciones en función de la aparición de un evento. Por ejemplo, los siguientes objetos EventTrigger especifican que, cuando el puntero del mouse entre en el elemento ListBoxItem, la propiedad MaxHeight se establezca en 90 durante un período de 0.2 segundos. Cuando el mouse sale del elemento, la propiedad se establece de nuevo en el valor original durante un período de 1 segundo. Observe que no es necesario especificar el valor de la propiedad To para la animación MouseLeave. Esto se debe a que la animación puede realizar un seguimiento del valor original.

<EventTrigger RoutedEvent="Mouse.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:0.2"
          Storyboard.TargetProperty="MaxHeight"
          To="90"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:1"
          Storyboard.TargetProperty="MaxHeight"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

Para obtener más información, vea Información general sobre objetos Storyboard.

En la captura de pantalla siguiente, el mouse está señalando el tercer elemento:

Captura de pantalla de ejemplo de aplicación de estilos

MultiTrigger, DataTrigger y MultiDataTrigger

Además de Trigger y EventTrigger, hay otros tipos de desencadenadores. MultiTrigger permite establecer valores de propiedad en función de varias condiciones. DataTrigger y MultiDataTrigger se utilizan cuando la propiedad de la condición está enlazada a datos.

Para obtener el ejemplo completo que se explica en esta información general, vea Ejemplo Introduction to Styling and Templating.

Recursos y temas compartidos

Una aplicación Windows Presentation Foundation (WPF) típica puede tener varios recursos de interfaz de usuario aplicados en toda la aplicación. Este conjunto de recursos puede considerarse el tema de la aplicación. Windows Presentation Foundation (WPF) proporciona compatibilidad para empaquetar los recursos de la interfaz de usuario como un tema utilizando un diccionario de recursos encapsulado como la clase ResourceDictionary.

Los temas de Windows Presentation Foundation (WPF) se definen mediante el mecanismo de estilos y plantillas que Windows Presentation Foundation (WPF) expone para personalizar los efectos visuales de cualquier elemento.

Los recursos de tema de Windows Presentation Foundation (WPF) están almacenados en diccionarios de recursos incrustados. Estos diccionarios de recursos deben incrustarse en un ensamblado firmado y pueden incrustarse en el mismo ensamblado que el propio código o en un ensamblado paralelo. En el caso de PresentationFramework.dll, el ensamblado que contiene los controles de Windows Presentation Foundation (WPF), los recursos de tema están en una serie de ensamblados paralelos.

El tema se convierte en el último lugar donde se va a buscar el estilo de un elemento. Normalmente, la búsqueda de un recurso adecuado se realizará recorriendo primero de manera ascendente el árbol de elementos; a continuación, se buscará en la colección de recursos de la aplicación y, finalmente, se consultará el sistema. De este modo, los autores de aplicaciones podrán redefinir el estilo de cualquier objeto en el nivel de árbol o de aplicación antes de alcanzar el tema.

Los diccionarios de recursos se pueden definir como archivos individuales que permiten reutilizar un tema en varias aplicaciones. También se pueden crear temas intercambiables definiendo varios diccionarios de recursos que proporcionen los mismos tipos de recursos pero con diferentes valores. Redefinir estos estilos u otros recursos en el nivel de aplicación es el enfoque recomendado para aplicar una máscara a una aplicación.

Para compartir un conjunto de recursos entre aplicaciones, incluidos los estilos y las plantillas, puede crear un archivo XAML y definir un objeto ResourceDictionary. Por ejemplo, eche una mirada a la siguiente captura de pantalla que muestra parte del Ejemplo Styling with ControlTemplates:

Ejemplos de plantillas de controles

Si se fija en los archivos XAML del ejemplo, observará que todos los archivos tienen lo siguiente:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

Es el uso compartido de shared.xaml, que define un objeto ResourceDictionary que contiene un conjunto de recursos de estilo y de pincel que permite que los controles del ejemplo tengan una apariencia coherente.

Para obtener más información, vea Diccionarios de recursos combinados.

Si crea un tema para el control personalizado, eche una mirada a la sección Biblioteca de controles externos de Información general sobre la creación de controles.

Vea también

Tareas

Cómo: Buscar elementos generados por un objeto ControlTemplate

Cómo: Buscar elementos generados por un objeto DataTemplate

Demo Photo Store

Conceptos

URIs de paquete en Windows Presentation Foundation

Otros recursos

Temas