Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
As aplicações .NET Multi-platform App UI (.NET MAUI) frequentemente contêm múltiplos controlos com uma aparência idêntica. Por exemplo, uma aplicação pode ter várias Label instâncias com as mesmas opções de fonte e layout:
<Label Text="These labels"
HorizontalOptions="Center"
VerticalOptions="Center"
FontSize="18" />
<Label Text="are not"
HorizontalOptions="Center"
VerticalOptions="Center"
FontSize="18" />
<Label Text="using styles"
HorizontalOptions="Center"
VerticalOptions="Center"
FontSize="18" />
Neste exemplo, cada Label objeto tem valores de propriedade idênticos para controlar a aparência do texto apresentado pelo Label. No entanto, definir a aparência de cada controlo individual pode ser repetitivo e propenso a erros. Em vez disso, pode ser criado um estilo que defina a aparência e depois aplicado aos controlos necessários.
Introdução aos estilos
Uma aplicação pode ser estilizada usando a Style classe para agrupar uma coleção de valores de propriedade num único objeto que pode depois ser aplicado a múltiplos elementos visuais. Isto ajuda a reduzir a marcação repetitiva e permite que a aparência de uma aplicação seja mais facilmente alterada.
Embora os estilos sejam concebidos principalmente para aplicações baseadas em XAML, também podem ser criados em C#:
- Style os objetos criados em XAML são geralmente definidos num ResourceDictionary que é atribuído à coleção de um controlo, de uma página, ou à coleção da aplicação.
- Style os objetos criados em C# são tipicamente definidos na classe da página, ou numa classe que pode ser acedida globalmente.
Escolher onde definir um Style afeta onde ele pode ser utilizado.
- Style Instâncias definidas no nível do controlo só podem ser aplicadas ao controlo e aos seus elementos filhos.
- Style As instâncias definidas ao nível de página só podem ser aplicadas à própria página e às suas descendentes.
- Style As instâncias definidas ao nível da aplicação podem ser aplicadas em toda a aplicação.
Cada Style objeto contém uma coleção de um ou mais Setter objetos, sendo que cada Setter possui um Property e um Value. O Property é o nome da propriedade vinculável do elemento ao qual o estilo é aplicado, e o Value é o valor aplicado à propriedade.
Cada Style objeto pode ser explícito ou implícito:
- Um objeto explícitoStyle é definido especificando a
TargetTypee umx:Keyvalor, e definindo a propriedade do Style elemento alvo para ax:Keyreferência. Para mais informações, veja Estilos explícitos. - Um objeto implícitoStyle é definido especificando apenas um
TargetType. O Style objeto será então automaticamente aplicado a todos os elementos desse tipo. No entanto, as subclasses deTargetTypenão têm automaticamente o Style aplicado. Para mais informações, veja Estilos implícitos.
Ao criar um Style, a TargetType propriedade é sempre necessária. O exemplo seguinte mostra um estilo explícito :
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="FontSize" Value="18" />
</Style>
Para aplicar um Style, o objeto alvo deve ser um VisualElement cujo valor da propriedade TargetType corresponda ao do Style:
<Label Text="Demonstrating an explicit style" Style="{StaticResource labelStyle}" />
Estilos inferiores na hierarquia de visualizações têm precedência sobre os definidos mais acima. Um exemplo seria definir um Style que define Label.TextColor para Red no nível da aplicação como sendo substituído por um estilo no nível da página que define Label.TextColor para Green. De forma semelhante, um estilo ao nível da página será sobreposto por um estilo ao nível de controlo. Além disso, se Label.TextColor estiver definido diretamente numa propriedade de controlo, isto tem prioridade sobre quaisquer estilos.
Os estilos não respondem a alterações de propriedade e permanecem inalterados durante toda a duração da aplicação. No entanto, as aplicações podem responder dinamicamente a alterações de estilo em tempo de execução, utilizando recursos dinâmicos. Para obter mais informações, consulte Estilos dinâmicos.
Estilos explícitos
Para criar um Style ao nível da página, um ResourceDictionary deve ser adicionado à página e, em seguida, pode-se incluir uma ou mais declarações Style no ResourceDictionary. Um Style é tornado explícito ao atribuir à sua declaração um atributo x:Key, que lhe confere uma chave descritiva no ResourceDictionary.
Estilos explícitos devem então ser aplicados a elementos visuais específicos, definindo as suas Style propriedades.
O exemplo seguinte mostra estilos explícitos na ResourceDictionarypágina , e aplicados aos objetos da Label página:
<ContentPage ...>
<ContentPage.Resources>
<Style x:Key="labelRedStyle"
TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="FontSize" Value="18" />
<Setter Property="TextColor" Value="Red" />
</Style>
<Style x:Key="labelGreenStyle"
TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="FontSize" Value="18" />
<Setter Property="TextColor" Value="Green" />
</Style>
<Style x:Key="labelBlueStyle"
TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="FontSize" Value="18" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ContentPage.Resources>
<StackLayout>
<Label Text="These labels"
Style="{StaticResource labelRedStyle}" />
<Label Text="are demonstrating"
Style="{StaticResource labelGreenStyle}" />
<Label Text="explicit styles,"
Style="{StaticResource labelBlueStyle}" />
<Label Text="and an explicit style override"
Style="{StaticResource labelBlueStyle}"
TextColor="Teal" />
</StackLayout>
</ContentPage>
Neste exemplo, define ResourceDictionary três estilos que estão explicitamente definidos nos objetos da Label página. Cada um Style é usado para mostrar texto numa cor diferente, ao mesmo tempo que define o tamanho da fonte e as opções de layout horizontal e vertical. Cada Style é aplicado a um Label diferente, definindo as propriedades de Style usando a extensão de marcação StaticResource. Além disso, embora o último Label tenha um Style definido, também altera a propriedade TextColor para um valor Color diferente.
Estilos implícitos
Para criar um Style ao nível da página, um ResourceDictionary deve ser adicionado à página e, em seguida, pode-se incluir uma ou mais declarações Style no ResourceDictionary. A Styletorna-se implícito por não especificar um x:Key atributo. O estilo será então aplicado a elementos visuais em questão que correspondam exatamente ao TargetType, mas não a elementos derivados do valor de TargetType.
O seguinte exemplo de código mostra um estilo implícito na ResourceDictionarypágina , aplicado aos objetos da Entry página:
<ContentPage ...>
<ContentPage.Resources>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="BackgroundColor" Value="Yellow" />
<Setter Property="FontAttributes" Value="Italic" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ContentPage.Resources>
<StackLayout>
<Entry Text="These entries" />
<Entry Text="are demonstrating" />
<Entry Text="implicit styles," />
<Entry Text="and an implicit style override"
BackgroundColor="Lime"
TextColor="Red" />
<local:CustomEntry Text="Subclassed Entry is not receiving the style" />
</StackLayout>
</ContentPage>
Neste exemplo, o ResourceDictionary define um único estilo implícito que está implicitamente definido nos objetos da Entry página. O Style é utilizado para exibir texto azul sobre um fundo amarelo, enquanto também define outras opções de aparência. O Style é adicionado às páginas ResourceDictionary sem especificar um x:Key atributo. Portanto, o Style é aplicado a todos os Entry objetos implicitamente, pois correspondem exatamente à TargetType propriedade do Style . No entanto, o Style não é aplicado ao CustomEntry objeto, que é uma subclasse Entry. Além disso, o quarto Entry sobrepõe as propriedades BackgroundColor e TextColor do estilo para diferentes valores Color.
Aplicar um estilo a tipos derivados
A Style.ApplyToDerivedTypes propriedade permite aplicar um estilo a controlos derivados do tipo base referenciado pela TargetType propriedade. Portanto, definir a propriedade true ativa um único estilo para visar múltiplos tipos, desde que os tipos sejam derivados do tipo base especificado na propriedade TargetType.
O exemplo seguinte mostra um estilo implícito que define a cor de fundo das Button instâncias para vermelho:
<Style TargetType="Button"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="Red" />
</Style>
Colocar este estilo num nível ResourceDictionary de página resultará na sua aplicação a todos Button os objetos na página, bem como a quaisquer controlos que derivem de Button. No entanto, se a ApplyToDerivedTypes propriedade permanecesse sem definir, o estilo seria aplicado apenas a Button objetos.
Estilos globais
Os estilos podem ser definidos globalmente ao adicioná-los ao dicionário de recursos da aplicação. Estes estilos podem então ser consumidos em toda a aplicação e ajudam a evitar duplicação de estilos entre páginas e controlos.
O exemplo seguinte mostra um Style definido ao nível da aplicação:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Styles"
x:Class="Styles.App">
<Application.Resources>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="HorizontalOptions"
Value="Center" />
<Setter Property="VerticalOptions"
Value="Center" />
<Setter Property="BorderColor"
Value="Lime" />
<Setter Property="CornerRadius"
Value="5" />
<Setter Property="BorderWidth"
Value="5" />
<Setter Property="WidthRequest"
Value="200" />
<Setter Property="TextColor"
Value="Teal" />
</Style>
</Application.Resources>
</Application>
Neste exemplo, o ResourceDictionary define um único estilo explícito , buttonStyle, que será usado para definir a aparência dos Button objetos.
Observação
Os estilos globais podem ser explícitos ou implícitos.
O exemplo seguinte mostra uma página a consumir o buttonStyle nos objetos do Button da página:
<ContentPage ...>
<StackLayout>
<Button Text="These buttons"
Style="{StaticResource buttonStyle}" />
<Button Text="are demonstrating"
Style="{StaticResource buttonStyle}" />
<Button Text="application styles"
Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage>
Herança de estilo
Os estilos podem herdar de outros estilos para reduzir duplicações e permitir a reutilização. Isto é conseguido definindo a Style.BasedOn propriedade para um existente Style. Em XAML, isto pode ser conseguido ao definir a propriedade BasedOn como uma extensão de marcação StaticResource que faz referência a um Style.
pt-PT: Estilos que herdam de um estilo base podem incluir Setter instâncias para novas propriedades, ou usá-las para substituir setters do estilo base. Além disso, estilos que herdam de um estilo base devem visar o mesmo tipo, ou um tipo que derive do tipo pretendido pelo estilo base. Por exemplo, se um estilo base se destina a View objetos, estilos baseados no estilo base podem direcionar View objetos ou tipos derivados da classe View, como objetos Label e Button.
Um estilo só pode herdar a partir de estilos do mesmo nível ou acima na hierarquia de visualização. Isto significa que:
- Um estilo ao nível da aplicação só pode herdar de outros estilos ao nível da aplicação.
- Um estilo de nível de página pode herdar de estilos de nível de aplicação e de outros estilos de nível de página.
- Um estilo de nível de controlo pode herdar de estilos de nível de aplicação, estilos de nível de página e outros estilos de nível de controlo.
O exemplo seguinte mostra herança de estilo explícita :
<ContentPage ...>
<ContentPage.Resources>
<Style x:Key="baseStyle"
TargetType="View">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ContentPage.Resources>
<StackLayout>
<StackLayout.Resources>
<Style x:Key="labelStyle"
TargetType="Label"
BasedOn="{StaticResource baseStyle}">
<Setter Property="FontSize" Value="18" />
<Setter Property="FontAttributes" Value="Italic" />
<Setter Property="TextColor" Value="Teal" />
</Style>
<Style x:Key="buttonStyle"
TargetType="Button"
BasedOn="{StaticResource baseStyle}">
<Setter Property="BorderColor" Value="Lime" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="BorderWidth" Value="5" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="TextColor" Value="Teal" />
</Style>
</StackLayout.Resources>
<Label Text="This label uses style inheritance"
Style="{StaticResource labelStyle}" />
<Button Text="This button uses style inheritance"
Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage>
Neste exemplo, os objetos baseStyle alvo View, e definem as propriedades HorizontalOptions e VerticalOptions. O baseStyle não está definido diretamente em nenhum controlo. Em vez disso, labelStyle e buttonStyle herdam dele, estabelecendo valores adicionais de propriedades vinculáveis. Os objetos labelStyle e buttonStyle são então colocados num Label e Button.
Importante
Um estilo implícito pode ser derivado de um estilo explícito, mas um estilo explícito não pode ser derivado de um estilo implícito.
Estilos Dinâmicos
Os estilos não respondem a alterações de propriedade e permanecem inalterados durante toda a duração da aplicação. Por exemplo, após atribuir a Style a a um elemento visual, se um dos Setter objetos for modificado, removido ou adicionado um novo Setter , as alterações deixarão de ser aplicadas ao elemento visual. No entanto, as aplicações podem responder dinamicamente a alterações de estilo em tempo de execução, utilizando recursos dinâmicos.
A extensão de marcação DynamicResource é semelhante à StaticResource no sentido em que ambas usam uma chave de dicionário para obter um valor de um ResourceDictionary. No entanto, enquanto o StaticResource realiza uma única consulta no dicionário, o DynamicResource mantém uma ligação à chave do dicionário. Portanto, se a entrada do dicionário associada à chave for substituída, a alteração é aplicada ao elemento visual. Isto permite que sejam feitas alterações de estilo em tempo de execução numa aplicação.
O exemplo seguinte mostra estilos dinâmicos :
<ContentPage ...>
<ContentPage.Resources>
<Style x:Key="baseStyle"
TargetType="View">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
<Style x:Key="blueSearchBarStyle"
TargetType="SearchBar"
BasedOn="{StaticResource baseStyle}">
<Setter Property="FontAttributes" Value="Italic" />
<Setter Property="PlaceholderColor" Value="Blue" />
</Style>
<Style x:Key="greenSearchBarStyle"
TargetType="SearchBar">
<Setter Property="FontAttributes" Value="None" />
<Setter Property="PlaceholderColor" Value="Green" />
</Style>
</ContentPage.Resources>
<StackLayout>
<SearchBar Placeholder="SearchBar demonstrating dynamic styles"
Style="{DynamicResource blueSearchBarStyle}" />
</StackLayout>
</ContentPage>
Neste exemplo, o SearchBar objeto usa a DynamicResource extensão de marcação para definir um Style chamado blueSearchBarStyle. Pode SearchBar então ter a sua Style definição atualizada em código:
Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];
Neste exemplo, a blueSearchBarStyle definição é atualizada para usar os valores da greenSearchBarStyle definição. Quando este código é executado, o SearchBar será atualizado para usar os Setter objetos definidos em greenSearchBarStyle.
Herança dinâmica de estilos
Derivar um estilo a partir de um estilo dinâmico não pode ser conseguido usando essa Style.BasedOn propriedade. Em vez disso, a Style classe inclui a BaseResourceKey propriedade, que pode ser definida para uma chave de dicionário cujo valor pode mudar dinamicamente.
O exemplo seguinte mostra a herança dinâmica do estilo:
<ContentPage ...>
<ContentPage.Resources>
<Style x:Key="baseStyle"
TargetType="View">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
<Style x:Key="blueSearchBarStyle"
TargetType="SearchBar"
BasedOn="{StaticResource baseStyle}">
<Setter Property="FontAttributes" Value="Italic" />
<Setter Property="TextColor" Value="Blue" />
</Style>
<Style x:Key="greenSearchBarStyle"
TargetType="SearchBar">
<Setter Property="FontAttributes" Value="None" />
<Setter Property="TextColor" Value="Green" />
</Style>
<Style x:Key="tealSearchBarStyle"
TargetType="SearchBar"
BaseResourceKey="blueSearchBarStyle">
<Setter Property="BackgroundColor" Value="Teal" />
<Setter Property="CancelButtonColor" Value="White" />
</Style>
</ContentPage.Resources>
<StackLayout>
<SearchBar Text="SearchBar demonstrating dynamic style inheritance"
Style="{StaticResource tealSearchBarStyle}" />
</StackLayout>
</ContentPage>
Neste exemplo, o SearchBar objeto usa a StaticResource extensão de marcação para referenciar um Style, chamado tealSearchBarStyle. Isto Style define algumas propriedades adicionais e usa a BaseResourceKey propriedade para referenciar blueSearchBarStyle. A DynamicResource extensão de marcação não é necessária porque tealSearchBarStyle não muda, exceto daquilo de que deriva Style. Por isso, tealSearchBarStyle mantém um link para blueSearchBarStyle e é atualizado quando o estilo base muda.
A blueSearchBarStyle definição pode ser atualizada em código:
Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];
Neste exemplo, a blueSearchBarStyle definição é atualizada para usar os valores da greenSearchBarStyle definição. Quando este código é executado, o SearchBar será atualizado para usar os Setter objetos definidos em greenSearchBarStyle.
Classes de estilo
As classes de estilo permitem que múltiplos estilos sejam aplicados a um controlo, sem recorrer à herança de estilos.
Uma classe de estilo pode ser criada definindo a propriedade Class de um Style para um string que representa o nome da classe. A vantagem que isto oferece, em vez de definir um estilo explícito usando o x:Key atributo, é que múltiplas classes de estilo podem ser aplicadas a um VisualElement.
Importante
Vários estilos podem partilhar o mesmo nome de classe, desde que visem tipos diferentes. Isto permite que múltiplas classes de estilo, com nomes idênticos, visem tipos diferentes.
O exemplo seguinte mostra três BoxView classes de estilo e uma VisualElement classe de estilo:
<ContentPage ...>
<ContentPage.Resources>
<Style TargetType="BoxView"
Class="Separator">
<Setter Property="BackgroundColor"
Value="#CCCCCC" />
<Setter Property="HeightRequest"
Value="1" />
</Style>
<Style TargetType="BoxView"
Class="Rounded">
<Setter Property="BackgroundColor"
Value="#1FAECE" />
<Setter Property="HorizontalOptions"
Value="Start" />
<Setter Property="CornerRadius"
Value="10" />
</Style>
<Style TargetType="BoxView"
Class="Circle">
<Setter Property="BackgroundColor"
Value="#1FAECE" />
<Setter Property="WidthRequest"
Value="100" />
<Setter Property="HeightRequest"
Value="100" />
<Setter Property="HorizontalOptions"
Value="Start" />
<Setter Property="CornerRadius"
Value="50" />
</Style>
<Style TargetType="VisualElement"
Class="Rotated"
ApplyToDerivedTypes="true">
<Setter Property="Rotation"
Value="45" />
</Style>
</ContentPage.Resources>
</ContentPage>
Neste exemplo, as classes de estilo Separator, Rounded e Circle definem propriedades BoxView para valores específicos. A Rotated classe de estilo tem um TargetTypeVisualElement, o que significa que só pode ser aplicada às VisualElement instâncias. No entanto, a sua ApplyToDerivedTypes propriedade é definida como true, o que garante que pode ser aplicada a quaisquer controlos que derivem de VisualElement, como BoxView. Para mais informações sobre como aplicar um estilo a um tipo derivado, veja Aplicar um estilo a tipos derivados.
As classes de estilo podem ser consumidas ao definir a propriedade StyleClass do controlo, do tipo IList<string>, como uma lista de nomes de classes de estilo. As classes de estilo serão aplicadas, desde que o tipo de controlo corresponda ao TargetType das classes de estilo.
O exemplo seguinte mostra três BoxView instâncias, cada uma atribuída a diferentes classes de estilo:
<ContentPage ...>
<ContentPage.Resources>
...
</ContentPage.Resources>
<StackLayout>
<BoxView StyleClass="Separator" />
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
StyleClass="Rounded, Rotated" />
<BoxView HorizontalOptions="Center"
StyleClass="Circle" />
</StackLayout>
</ContentPage>
Neste exemplo, o primeiro BoxView é desenhado para ser um separador de linha, enquanto o terceiro BoxView é circular. O segundo BoxView tem duas classes de estilo aplicadas, que lhe dão cantos arredondados e rodam-no em 45 graus.
Importante
Múltiplas classes de estilo podem ser aplicadas a um controlo porque a StyleClass propriedade é do tipo IList<string>. Quando isto ocorre, as classes de estilo são aplicadas pela ordem crescente da lista. Portanto, quando múltiplas classes de estilo definem propriedades idênticas, a propriedade na classe de estilo que está na posição mais alta da lista terá prioridade.
Invalidar e reaplicar um estilo
Quando se modificam os valores do setter de a Style em tempo de execução, os controlos que usam esse estilo não refletem automaticamente as alterações. O InvalidateStyle() método força um controlo a desaplicar e reaplicar o seu estilo atual combinado, o que faz com que os valores atualizados do setter sejam aplicados.
O exemplo seguinte modifica o valor do setter de um estilo e depois executa InvalidateStyle em cada controlo afetado:
// Find the style defined in resources.
var myStyle = (Style)Resources["myLabelStyle"];
// Modify a setter value in-place.
myStyle.Setters[0].Value = Colors.Red;
// Force the controls to pick up the change.
myLabel1.InvalidateStyle();
myLabel2.InvalidateStyle();
Observação
InvalidateStyle é uma API orientada pelo chamador — .NET MAUI não deteta automaticamente quando os valores do setter mudam. Deves chamar este método em cada controlo que deva refletir o estilo atualizado.
O InvalidateStyle método está definido em StyleableElement e também está disponível em Span e ImageSource.