Como criar um estilo para um controle (WPF .NET)

Com o Windows Presentation Foundation (WPF), você pode personalizar a aparência de um controle existente com seu próprio estilo reutilizável. Os estilos podem ser aplicados globalmente ao seu aplicativo, janelas e páginas ou diretamente aos controles.

Importante

A documentação do Guia da Área de Trabalho para .NET 7 e .NET 6 está em construção.

Criar um estilo

Você pode pensar em um como uma maneira conveniente de aplicar um conjunto de valores de propriedade a um Style ou mais elementos. Você pode usar um estilo em qualquer elemento derivado de FrameworkElement ou FrameworkContentElement como um ou um WindowButtonarquivo .

A maneira mais comum de declarar um estilo é como um recurso na Resources seção em um arquivo XAML. Como os estilos são recursos, eles obedecem às mesmas regras de escopo que se aplicam a todos os recursos. Simplificando, onde você declara um estilo afeta onde o estilo pode ser aplicado. Por exemplo, se você declarar o estilo no elemento raiz do arquivo XAML de definição do aplicativo, o estilo poderá ser usado em qualquer lugar do aplicativo.

<Application x:Class="IntroToStylingAndTemplating.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:IntroToStylingAndTemplating"
             StartupUri="WindowExplicitStyle.xaml">
    <Application.Resources>
        <ResourceDictionary>
            
            <Style x:Key="Header1" TargetType="TextBlock">
                <Setter Property="FontSize" Value="15" />
                <Setter Property="FontWeight" Value="ExtraBold" />
            </Style>
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

Se você declarar o estilo em um dos arquivos XAML do aplicativo, o estilo poderá ser usado somente nesse arquivo XAML. Para obter mais informações sobre regras de escopo para recursos, consulte Visão geral dos recursos XAML.

<Window x:Class="IntroToStylingAndTemplating.WindowSingleResource"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IntroToStylingAndTemplating"
        mc:Ignorable="d"
        Title="WindowSingleResource" Height="450" Width="800">
    <Window.Resources>
        
        <Style x:Key="Header1" TargetType="TextBlock">
            <Setter Property="FontSize" Value="15" />
            <Setter Property="FontWeight" Value="ExtraBold" />
        </Style>
        
    </Window.Resources>
    <Grid />
</Window>

Um estilo é composto de <Setter> elementos filho que definem propriedades nos elementos aos quais o estilo é aplicado. No exemplo acima, observe que o estilo está definido para ser aplicado a TextBlock tipos por meio do TargetType atributo. O estilo definirá o FontSize para e o FontWeight para ExtraBold15 . Adicione um <Setter> para cada propriedade que o estilo altera.

Aplicar um estilo implicitamente

A Style é uma maneira conveniente de aplicar um conjunto de valores de propriedade a mais de um elemento. Por exemplo, considere os seguintes TextBlock elementos e sua aparência padrão em uma janela.

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

Styling sample screenshot before

Você pode alterar a aparência padrão definindo propriedades, como FontSize e FontFamily, em cada TextBlock elemento diretamente. No entanto, se você quiser que seus TextBlock elementos compartilhem algumas propriedades, poderá criar um Style na seção do Resources arquivo XAML, conforme mostrado aqui.

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

Quando você define o do seu estilo para o tipo e omite o atributo, o estilo é aplicado a todos os TextBlock elementos com escopo para o estilo, que geralmente é o x:KeyTargetTypeTextBlock próprio arquivo XAML.

Agora, os TextBlock elementos aparecem da seguinte maneira.

Styling sample screenshot base style

Aplicar um estilo explicitamente

Se você adicionar um x:Key atributo com valor ao estilo, o estilo não será mais aplicado implicitamente a todos os elementos do TargetType. Somente os elementos que fazem referência explícita ao estilo terão o estilo aplicado a eles.

Aqui está o estilo da seção anterior, mas declarado com o x:Key atributo.

<Window.Resources>
    <Style x:Key="TitleText" TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

Para aplicar o estilo, defina a Style propriedade no elemento para o x:Key valor, usando uma extensão de marcação StaticResource, conforme mostrado aqui.

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

Observe que o primeiro TextBlock elemento tem o estilo aplicado a ele, enquanto o segundo elemento TextBlock permanece inalterado. O estilo implícito da seção anterior foi alterado para um estilo que declarava o atributo, ou seja, o x:Key único elemento afetado pelo estilo é aquele que fez referência direta ao estilo.

Styling sample screenshot textblock

Uma vez que um estilo é aplicado, explícita ou implicitamente, ele se torna selado e não pode ser alterado. Se você quiser alterar um estilo que foi aplicado, crie um novo estilo para substituir o existente. Para obter mais informações, consulte a propriedade IsSealed.

É possível criar um objeto que escolhe um estilo para aplicar com base na lógica personalizada. Para obter um exemplo, consulte o exemplo fornecido para a StyleSelector classe.

Aplicar um estilo programaticamente

Para atribuir um estilo nomeado a um elemento programaticamente, obtenha o estilo da coleção de recursos e atribua-o à propriedade do Style elemento. Os itens em uma coleção de recursos são do tipo Object. Portanto, você deve converter o estilo recuperado em um System.Windows.Style antes de atribuí-lo à Style propriedade. Por exemplo, o código a seguir define o estilo de um TextBlock nomeado textblock1 para o estilo TitleTextdefinido .

textblock1.Style = (Style)Resources["TitleText"];
textblock1.Style = CType(Resources("TitleText"), Windows.Style)

Estender um estilo

Talvez você queira que seus dois TextBlock elementos compartilhem alguns valores de propriedade, como o e o FontFamily centralizado HorizontalAlignment. Mas você também deseja que o texto Minhas Imagens tenha algumas propriedades adicionais. Você pode fazer isso criando um novo estilo baseado no primeiro estilo, como mostrado aqui.

<Window.Resources>
    <!-- .... other 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>
    
    <!--A Style that extends the previous TextBlock 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>
<StackPanel>
    <TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Esse TextBlock estilo agora está centralizado, usa uma Comic Sans MS fonte com um tamanho de , e a cor de 26primeiro plano definida como a mostrada LinearGradientBrush no exemplo. Observe que ele substitui o FontSize valor do estilo base. Se houver mais de um apontando para a mesma propriedade em um SetterStyle, o que é declarado Setter último terá precedência.

O seguinte mostra como os TextBlock elementos agora se parecem:

Styled TextBlocks

Esse TitleText estilo estende o estilo que foi criado para o tipo, referenciado TextBlock com BasedOn="{StaticResource {x:Type TextBlock}}". Você também pode estender um estilo que tenha um x:Key usando o x:Key do estilo. Por exemplo, se houvesse um estilo chamado Header1 e você quisesse estender esse estilo, você usaria BasedOn="{StaticResource Header1}"o .

Relação da propriedade TargetType e do atributo x:Key

Como mostrado anteriormente, definir a propriedade como TextBlock sem atribuir o estilo an x:Key faz com que o estilo seja aplicado a TargetType todos os TextBlock elementos. Nesse caso, o x:Key é definido implicitamente como {x:Type TextBlock}. Isso significa que, se você definir explicitamente o valor para qualquer coisa diferente de {x:Type TextBlock}, o x:KeyStyle não será aplicado a todos os TextBlock elementos automaticamente. Em vez disso, você deve aplicar o estilo (usando o x:Key valor) aos TextBlock elementos explicitamente. Se o seu estilo estiver na seção de recursos e você não definir a TargetType propriedade no seu estilo, deverá definir o x:Key atributo.

Além de fornecer um valor padrão para o , a TargetType propriedade especifica o x:Keytipo ao qual as propriedades setter se aplicam. Se você não especificar um , deverá qualificar as propriedades em seus Setter objetos com um TargetTypenome de classe usando a sintaxe Property="ClassName.Property". Por exemplo, em vez de definir , você deve definir Property="FontSize"Property como "TextBlock.FontSize" ou "Control.FontSize".

Observe também que muitos controles WPF consistem em uma combinação de outros controles WPF. Caso você crie um estilo que se aplica a todos os controles de um tipo, pode obter resultados inesperados. Por exemplo, se você criar um estilo direcionado ao TextBlock tipo em um , o estilo será aplicado a todos os TextBlock controles na janela, mesmo que o TextBlock seja parte de outro controle, como um WindowListBox.

Confira também