Estilos de XAML

É possível personalizar a aparência de seus aplicativos de muitas formas usando a estrutura XAML. Os estilos permitem definir propriedades de controle e reutilizar essas configurações para criar uma aparência consistente em vários controles.

WinUI e estilos

A partir do WinUI 2.2, usamos a WinUI (Biblioteca de Interface do Usuário do Windows) para fornecer novas atualizações de estilo visual em nossos componentes de interface do usuário. Se você perceber que a interface do usuário não está sendo atualizada para os estilos mais recentes, atualize para o pacote NuGet da WinUI mais recente.

A partir do WinUI 2.6, fornecemos novos estilos para a maioria dos controles e um novo sistema de controle de versão que permite que você reverter aos estilos de controle anteriores, se necessário. Incentivamos você a usar os novos estilos, pois eles correspondem melhor à direção de design do Windows. No entanto, se o cenário não puder dar suporte aos novos estilos, as versões anteriores ainda estarão disponíveis.

Você pode alterar a versão de estilo definindo a ControlsResourcesVersion propriedade no XamlControlsResources que você inclui em quando Application.Resources usa o WinUI versão 2. ControlsResourcesVersion usa como padrão o valor Version2de enumeração .

Definir esse valor Version1 como faz XamlControlsResources com que carregue as versões de estilo anteriores em vez dos novos estilos usados pela versão mais recente do WinUI. Não há suporte para a alteração dessa propriedade no runtime e a funcionalidade de recarregamento frequente do VisualStudio não funcionará; no entanto, depois de recompilar o aplicativo, você verá os estilos de controle mudarem.

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

Noções básicas de estilos

Use estilos para extrair configurações de propriedades visuais para recursos reutilizáveis. Aqui está um exemplo que mostra 3 botões com um estilo que define as propriedades BorderBrush, BorderThickness e Foreground. Ao aplicar um estilo, você torna igual a aparência dos controles sem precisar definir essas propriedades em cada controle separadamente.

Captura de tela de três botões estilizados dispostos lado a lado.

Você pode definir um estilo embutido na linguagem XAML para um controle, ou como um recurso reutilizável. Defina recursos no arquivo XAML de uma página individual, no arquivo App.xaml ou em um arquivo XAML de dicionário de recursos separado. Um arquivo XAML do dicionário de recursos pode ser compartilhado entre aplicativos e mais de um dicionário de recursos pode ser mesclado em um único aplicativo. O local onde o recurso é definido determina o escopo no qual ele pode ser usado. Recursos de nível de página estão disponíveis somente na página em que são definidos. Se recursos com a mesma chave forem definidos tanto no App.xaml quanto em uma página, o recurso na página substituirá o recurso no aplicativo App.xaml. Se um recurso estiver definido em um arquivo de dicionário de recurso separado, seu escopo será determinado pela referência de onde partiu o dicionário do recurso.

Na definição de Style, você precisa de um atributo TargetType e de uma coleção de um ou mais elementos Setter. O atributo TargetType é uma cadeia de caracteres que especifica um tipo FrameworkElement ao qual aplicar o estilo. O valor de TargetType deve especificar um tipo derivado de FrameworkElement definido pelo Windows Runtime ou um tipo personalizado disponível em um assembly referenciado. Se você tentar aplicar um estilo a um controle, e o tipo do controle não corresponder ao atributo TargetType do estilo que você está tentando aplicar, uma exceção ocorrerá.

Cada elemento Setter requer uma Property e um Value. Essas configurações de propriedade indicam a qual propriedade de controle a configuração se aplica e qual é o valor a ser definido para essa propriedade. Você pode definir Setter.Value com a sintaxe de elemento de propriedade ou atributo. O XAML aqui mostra o estilo aplicado aos botões mostrados anteriormente. Nesse XAML, os dois primeiros elementos Setter usam a sintaxe de atributos, mas o último Setter para a propriedade BorderBrush usa a sintaxe de elementos de propriedade. O exemplo não usa o atributo x:Key; portanto, o estilo é aplicado implicitamente aos botões. A aplicação implícita ou explícita de estilos é explicada na próxima seção.

<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 um estilo implícito ou explícito

Se você definir um estilo como um recurso, haverá duas maneiras de aplicá-lo aos seus controles:

Se um estilo contiver o atributo x:Key, você só poderá aplicá-lo a um controle definindo a propriedade Style do controle como o estilo com chave. Por outro lado, um estilo sem um atributo x:Key é automaticamente aplicado a todos os controles do seu tipo de destino que, de outra forma, não teriam uma definição de estilo explícita.

Aqui há dois botões que demonstram estilos implícitos e explícitos.

botões com o estilo definido de forma implícita e explícita.

Neste exemplo, o primeiro estilo tem um atributo x:Key, e seu tipo de destino é Button. A propriedade Style do primeiro botão é definida para essa chave, de maneira que esse estilo é aplicado explicitamente. O segundo estilo é aplicado explicitamente ao segundo botão porque seu tipo de destino é Button e o estilo não tem um 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 baseados em outros

Para facilitar a manutenção de estilos e otimizar sua reutilização, você pode criar estilos que herdam de outros estilos. Você usa a propriedade BasedOn para criar estilos herdados. Estilos que herdam de outros estilos devem ter como destino o mesmo tipo de controle ou um controle derivado do tipo de destino do estilo base. Por exemplo, se um estilo base tiver como destino ContentControl, estilos baseados nesse estilo poderão ter como alvo ContentControl ou tipos derivados de ContentControl, como Button e ScrollViewer. Se um valor não é definido no estilo baseado, ele é herdado do estilo base. Para alterar um valor do estilo base, o estilo baseado substitui esse valor. O próximo exemplo mostra um Button e uma CheckBox com estilos herdados do mesmo estilo base.

botões estilizados com estilos baseados.

O estilo base tem como destino ContentControl e define as propriedades Height e Width. Os estilos baseados neste estilo têm como destino CheckBox e Button, que derivam de ContentControl. Os estilos baseados definem cores diferentes para as propriedades BorderBrush e Foreground. (Normalmente, você não coloca uma borda em torno de uma CheckBox. Fazemos isso aqui para mostrar os efeitos do 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>

Use ferramentas para trabalhar facilmente com estilos

Uma forma rápida de aplicar estilos aos seus controles é clicar com o botão direito do mouse em um controle na superfície de design XAML do Microsoft Visual Studio e selecionar Editar Estilo ou Editar Modelo (dependendo do controle no qual você está clicando com o botão direito). Você pode, então, aplicar um estilo existente selecionando Aplicar Recurso ou pode definir um novo estilo selecionando Criar Vazio. Se você criar um estilo vazio, terá a opção de defini-lo na página, no arquivo App.xaml ou em um dicionário de recursos separado.

Estilo leve

Substituir os pincéis do sistema é geralmente feito no nível do aplicativo ou da página e, em ambos os casos, a substituição de cor afetará todos os controles que fazem referência a esse pincel – e, em XAML, muitos controles podem referenciar o mesmo pincel de sistema.

Captura de tela de dois botões: um no estado de repouso e outro com estilo leve 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 (mouse passa sobre o botão), PointerPressed (botão foi invocado) ou Desabilitado (botão não é interativo). Essas terminações são acrescentadas aos nomes de estilo lightweight originais: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled etc. Modificar esses pincéis também garantirá que seus controles sejam coloridos de forma consistente com o tema do aplicativo.

Colocar essas substituições de pincel no nível App.Resources irá alterar todos os botões dentro do aplicativo inteiro, em vez de em uma única página.

Estilo por controle

Em outros casos, é desejável mudar um único controle em uma página somente para ter uma determinada aparência, sem alterar outras versões daquele controle:

Captura de tela de três botões estilizados, empilhados uns sobre os outros.

<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"/>

Isso só afetaria uma "Caixa de Seleção Especial" na página em que esse controle existia.

Controles personalizados

Ao criar seus próprios controles personalizados que podem estar alinhados visual e/ou funcionalmente com nossos controles internos, considere usar estilo implícito e recursos de estilo lightweight para definir seu conteúdo personalizado. Você pode usar os recursos diretamente ou criar um novo alias para o recurso.

Usando recursos de controle diretamente

Por exemplo, se você estiver escrevendo um controle semelhante a um Botão, poderá fazer com que o controle faça referência diretamente aos recursos do botão, desta forma:

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

Aliasing control resources to new names

Como alternativa, se você preferir criar seus próprios recursos, deverá alias esses nomes personalizados para nossos recursos de estilo lightweight padrão.

Por exemplo, o estilo do controle personalizado pode ter definições de recursos especiais:

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

Em seu Dicionário de Recursos ou main definição, você conectaria os recursos de estilo lightweight aos seus 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>

É necessário que você use um ThemeDictionary duplicado três vezes para manipular as três alterações de tema diferentes corretamente (Default, Light, HighContrast).

Cuidado

Se você atribuir um recurso de estilo Lightweight a um novo alias e também redefinir o recurso de estilo Lightweight, sua personalização poderá não ser aplicada se a pesquisa de recursos não estiver na ordem correta. Por exemplo, se você substituir ButtonBackground em um local que é pesquisado antes MyCustomControlBackground de ser encontrado, a substituição será perdida.

Evitar reestilamento de controles

A Biblioteca de Interface do Usuário do Windows 2.2 ou posterior inclui novos estilos e modelos para controles winui e do sistema.

A melhor maneira de se manter atualizado com nossos estilos visuais mais recentes é usar o pacote WinUI 2 mais recente e evitar estilos e modelos personalizados (também conhecidos como re-modelagem). Os estilos ainda são uma maneira conveniente de aplicar um conjunto de valores consistentemente entre controles em seu aplicativo. Ao fazer isso, certifique-se de se basear em nossos estilos mais recentes.

Para controles do sistema que usam estilos WinUI (Windows.UI.Xaml.Controls namespace), defina BasedOn="{StaticResource Default<ControlName>Style}", em que <ControlName> é o nome do controle. Por exemplo:

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

Para controles winui 2 (Microsoft.UI.Xaml.Controls namespace), o estilo padrão é definido nos metadados, portanto, omita BasedOn.

Controles derivados

Se você derivar um controle personalizado de um controle XAML existente, ele não obterá os estilos do WinUI 2 por padrão. Para aplicar os estilos do WinUI 2:

  • Crie um novo Style com seu TargetType definido como seu controle personalizado.
  • Baseie o Estilo no estilo padrão do controle do qual você derivava.

Um cenário comum para isso é derivar um novo controle de ContentDialog. Este exemplo mostra como criar um novo Estilo que se aplica DefaultContentDialogStyle à caixa de diálogo personalizada.

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

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

A propriedade Template

Um setter de estilo pode ser usado para a propriedade Template de um Control e, na verdade, isso compõe a maior parte de um estilo XAML típico e dos recursos XAML de um aplicativo. Isso é discutido com mais detalhes no tópico Modelos de controle.