Estilos XAML

El marco XAML te permite personalizar la apariencia de tus aplicaciones de varias maneras. Los estilos te permiten establecer propiedades de control y reusar esa configuración para mantener un aspecto uniforme en varios controles.

WinUI y estilos

A partir de WinUI 2.2, hemos usado la biblioteca de interfaz de usuario de Windows (WinUI) para ofrecer nuevas actualizaciones de estilo visual en nuestros componentes de interfaz de usuario. Si observa que la interfaz de usuario no se actualiza a los estilos más recientes, asegúrese de actualizar al paquete NuGet winUI más reciente.

A partir de WinUI 2.6, proporcionamos nuevos estilos para la mayoría de los controles y un nuevo sistema de control de versiones que le permite revertir a los estilos de control anteriores si es necesario. Te animamos a usar los nuevos estilos, ya que coinciden mejor con la dirección de diseño de Windows. Sin embargo, si su escenario no puede admitir los nuevos estilos, las versiones anteriores siguen estando disponibles.

Puede cambiar la versión de estilo estableciendo la ControlsResourcesVersion propiedad en la XamlControlsResources que se incluye en Application.Resources cuando se usa WinUI versión 2. ControlsResourcesVersion tiene como valor predeterminado el valor Version2de enumeración .

Establecer este valor en Version1 hace que XamlControlsResources cargue las versiones de estilo anteriores en lugar de los nuevos estilos usados por la versión más reciente de WinUI. No se admite cambiar esta propiedad en tiempo de ejecución y la funcionalidad de recarga activa de VisualStudio no funcionará; Sin embargo, después de recompilar la aplicación, verá que los estilos de control cambian.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

Conceptos básicos de estilos

Los estilos te permiten extraer opciones de configuración de propiedades visuales en recursos reutilizables. Este es un ejemplo en el que se muestran tres botones con un estilo que establece las propiedades BorderBrush, BorderThickness y Foreground. Al aplicar un estilo, puedes hacer que todos los controles tengan el mismo aspecto no tener que establecer estas propiedades en cada control de manera independiente.

Captura de pantalla de tres botones con estilo organizados en paralelo.

Puedes definir un estilo en línea en el lenguaje XAML para un control o como una fuente reutilizable. Define recursos en un archivo XAML de una página individual, en el archivo App.xaml o en un archivo XAML de diccionario de recursos independiente. Varias aplicaciones pueden compartir un mismo archivo XAML de diccionario de recursos y se pueden combinar varios diccionarios de recursos en una sola aplicación. El lugar donde se define el recurso determina el ámbito en el que puede usarse. Los recursos de nivel de página se encuentran disponibles solo en la página donde se definen. Si tanto en App.xaml como en la página se definen con la misma clave, el recurso de la página invalida al recurso de App.xaml. Si un recurso se define en un archivo de diccionario de recursos diferente, su ámbito se determina por el lugar donde se hace referencia al diccionario de recursos.

En la definición de Style, necesitas un atributo TargetType y una colección de uno o más elementos Setter. El atributo TargetType es una cadena que especifica un tipo FrameworkElement al que aplicarle el estilo. El valor TargetType debe especificar un tipo derivado de FrameworkElement definido por Windows Runtime o un tipo personalizado que esté disponible en un ensamblado referido. Si intentas aplicar un estilo a un control y el tipo del control no coincide con el atributo TargetType de dicho estilo, se produce una excepción.

Cada elemento Setter requiere una propiedad Property y una propiedad Value. Esta configuración de las propiedades indica a qué propiedades del control se aplica la configuración, y el valor que se fija para esa propiedad. Puedes establecer Setter.Value con sintaxis de atributo o elemento de propiedad. El XAML muestra el estilo que se aplica a los botones que se mostraron anteriormente. En este XAML, los dos primeros elementos Setter usan la sintaxis de atributo, pero el último Setter, para la propiedad BorderBrush, usa la sintaxis de elemento de propiedad. En el ejemplo no se usa el atributo x:Key, por lo que el estilo se aplica implícitamente a los botones. La aplicación de estilos de manera implícita o explícita se explica en la siguiente sección.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

Aplicar un estilo implícito o explícito

Si defines un estilo como un recurso, puedes aplicarlo a los controles de dos maneras:

Si un estilo contiene el atributo x:Key, solo puedes aplicarlo a un control mediante el establecimiento de la propiedad Style del control en el estilo con clave. Por el contrario, un estilo sin un atributo x:Key se aplica automáticamente a cada control de su tipo de destino si el control no tiene una opción de estilo explícita.

Aquí hay dos botones que muestran los estilos implícitos y explícitos.

botones con estilos implícitos y explícitos.

En este ejemplo, el primer estilo tiene un atributo x:Key y su tipo de destino es Button. La propiedad Style del primer botón se establece en esta clave, por lo que este estilo se aplica de manera explícita. El segundo estilo se aplica de manera implícita al segundo botón porque su tipo de destino es Botón y el estilo no tiene un atributo x:Key.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

Usar estilos heredados

Para crear estilos que sean más fáciles de mantener y optimizar la reutilización de estilos, puedes crear estilos que hereden de otros estilos. Usa la propiedad BasedOn para crear estilos heredados. Los estilos que heredan de otros estilos deben apuntar al mismo tipo de control o a uno que derive del tipo al que apunta el estilo base. Por ejemplo, si un estilo base apunta a ContentControl, los estilos que estén basados en este estilo pueden apuntar a ContentControl o a tipos que deriven de ContentControl, como Button y ScrollViewer. Si no se establece un valor en el estilo heredado, se hereda del estilo base. Para cambiar un valor del estilo base, el estilo heredado invalida ese valor. En el siguiente ejemplo se muestra un elemento Button y un elemento CheckBox con estilos que heredan del mismo estilo base.

botones con estilos que usan estilos heredados.

El estilo base apunta a ContentControl y establece las propiedades Height y Width. Los estilos basados en este estilo apuntan a CheckBox y Button, que derivan de ContentControl. Los estilos heredados establecen distintos colores para las propiedades BorderBrush y Foreground. (Normalmente, no coloca un borde alrededor de una casilla. Lo hacemos aquí para mostrar los efectos del estilo).

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Usar herramientas para trabajar con estilos fácilmente

Una manera rápida de aplicar estilos a los controles es hacer clic con el botón secundario en un control de la superficie de diseño XAML de Microsoft Visual Studio y seleccionar Editar estilo o Editar plantilla (según el control en el que estás haciendo clic con el botón secundario). Después, puedes aplicar un estilo existente si seleccionas Aplicar recurso o definir un estilo nuevo si seleccionas Crear vacío. Si creas un estilo vacío, tienes la opción de definirlo en la página, en el archivo App.xaml o en un diccionario de recursos independiente.

Estilos ligeros

Por norma general, los pinceles del sistema se reemplazan en el nivel de página o aplicación y, en cualquier caso, la sustitución del color afectará a todos los controles que hacen referencia a ese pincel. Además, en XAML, muchos controles pueden hacer referencia al mismo pincel del sistema.

Captura de pantalla de dos botones: uno en su estado de reposo y otro con un estilo ligero aplicado.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

Para estados como PointerOver (se sitúa el mouse sobre el botón), PointerPressed (se ha invocado el botón), o Disabled (el botón no es interactivos). Estos finales se anexan a los nombres de estilo ligero originales: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, etc. Al modificar esos pinceles también, se asegurará de que los controles estén coloreados de forma coherente con el tema de la aplicación.

Al colocar estos reemplazos de pincel en el nivel de recursos de la aplicación, se modificarán todos los botones de toda la aplicación, en lugar de en una sola página.

Estilos según el control

En otros casos se desea modificar un solo control de una página para que tenga un aspecto determinado, sin alterar ninguna otra versión de ese control:

Captura de pantalla de tres botones con estilo organizados apilados uno encima del otro.

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

Esto solo afectaría a que hubiera un "CheckBox especial" en la página donde existía ese control.

Controles personalizados

Cuando cree sus propios controles personalizados que puedan estar visualmente o funcionalmente alineados con nuestros controles integrados, considere la posibilidad de usar los recursos de estilo implícito y estilo ligero para definir el contenido personalizado. Puede usar los recursos directamente o crear un nuevo alias para el recurso.

Uso de recursos de control directamente

Por ejemplo, si está escribiendo un control similar a un botón, puede hacer que el control haga referencia directamente a los recursos del botón, de la siguiente manera:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

Alias de recursos de control para nuevos nombres

Como alternativa, si prefiere crear sus propios recursos, debe aplicar alias a esos nombres personalizados a nuestros recursos de estilo ligero predeterminados.

Por ejemplo, el estilo del control personalizado podría tener definiciones de recursos especiales:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

En el diccionario de recursos o la definición principal, enlazaría los recursos de estilo ligero a los personalizados:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Es necesario que use un ThemeDictionary que se duplica tres veces para controlar los tres cambios de tema diferentes correctamente (Default, , LightHighContrast).

Precaución

Si asigna un recurso de estilo ligero a un nuevo alias y también vuelve a definir el recurso de estilo ligero, es posible que la personalización no se aplique si la búsqueda de recursos no está en el orden correcto. Por ejemplo, si invalida ButtonBackground en un lugar que se busca antes MyCustomControlBackground de que se encuentre, se omitirá la invalidación.

Evitar controles de restyling

La biblioteca de interfaz de usuario de Windows 2.2 o posterior incluye nuevos estilos y plantillas para los controles winUI y del sistema.

La mejor manera de mantenerse al día con nuestros estilos visuales más recientes es usar el paquete WinUI 2 más reciente y evitar estilos y plantillas personalizados (también conocidos como re-plantillas). Los estilos siguen siendo una manera cómoda de aplicar un conjunto de valores de forma coherente entre los controles de la aplicación. Al hacerlo, asegúrese de basarse en nuestros estilos más recientes.

Para los controles del sistema que usan estilos winUI (Windows.UI.Xaml.Controls espacio de nombres), establezca BasedOn="{StaticResource Default<ControlName>Style}", donde <ControlName> es el nombre del control. Por ejemplo:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

Para los controles winUI 2 (Microsoft.UI.Xaml.Controls espacio de nombres), el estilo predeterminado se define en los metadatos, por lo que se omite BasedOn.

Controles derivados

Si derivas un control personalizado de un control XAML existente, no obtendrá los estilos de WinUI 2 de forma predeterminada. Para aplicar los estilos de WinUI 2:

  • Cree un nuevo estilo con su TargetType establecido en el control personalizado.
  • Base el estilo en el estilo predeterminado del control del que se deriva.

Un escenario común para esto es derivar un nuevo control de ContentDialog. En este ejemplo se muestra cómo crear un nuevo estilo que se aplique DefaultContentDialogStyle al cuadro de diálogo personalizado.

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

La propiedad Template

Se puede usar un establecedor de estilo para la propiedad Template de Control. De hecho, esto conforma la mayor parte de un estilo XAML típico y los recursos XAML de una aplicación. Esto se explica con más detalle en el tema Plantillas de control.