Criar uma interface do usuário consistente usando estilos
Os recursos são ótimos para evitar valores duplicados embutidos em código na marcação XAML, mas podem ser entediantes de aplicar. Você atribui cada valor da propriedade individualmente, o que pode resultar em XAML detalhado e sobrecarregado. Esta unidade mostra como agrupar várias configurações em um estilo, o que pode ajudar a organizar seu código e torná-lo mais sustentável.
Como os recursos podem sobrecarregar seu XAML
Um recurso fornece um valor para uma única propriedade. No entanto, o uso de muitos recursos pode levar a XAML detalhado. Suponha que você queira uma aparência personalizada para seus botões. Primeiro, você cria recursos para os valores necessários. Em seguida, aplica cada recurso a todos os seus botões. O código a seguir mostra a aparência da marcação XAML para dois botões.
<Button
Text = "OK"
BackgroundColor = "{StaticResource highlightColor}"
BorderColor = "{StaticResource borderColor}"
BorderWidth = "{StaticResource borderWidth}"
TextColor = "{StaticResource textColor}" />
<Button
Text = "Cancel"
BackgroundColor = "{StaticResource highlightColor}"
BorderColor = "{StaticResource borderColor}"
BorderWidth = "{StaticResource borderWidth}"
TextColor = "{StaticResource textColor}" />
Observe como as mesmas cinco propriedades são definidas em cada um dos botões. O uso de recursos elimina a necessidade de valores repetidos embutidos em código em quatro opções. No entanto, esse tipo de marcação XAML rapidamente fica difícil de ler. Além disso, se você estiver definindo um grande número de propriedades para cada controle, será fácil omitir acidentalmente uma delas, levando a inconsistências na aparência dos controles. A solução é criar um estilo que atribua todas as quatro propriedades ao mesmo tempo.
O que é um setter?
Os setters são os principais componentes que você usa para criar estilos.
Um setter é um contêiner para um par propriedade-valor. Você pode pensar em um setter como representando uma instrução de atribuição. Você especifica qual propriedade atribuir e o valor a ser aplicado. Normalmente, você cria objetos Setter em sua marcação XAML. O exemplo a seguir cria um objeto Setter para a propriedade TextColor.
<Setter Property="TextColor" Value="White" />
Você pode usar um recurso para o valor em um setter, conforme mostrado no código a seguir. Essa técnica é ótima quando você deseja usar o mesmo valor em vários setters.
<Setter Property="TextColor" Value="{StaticResource textColor}" />
Observação
O valor da propriedade que você especifica em um setter deve ser implementado como uma propriedade associável. Todas as propriedades em controles no .NET MAUI que terminam com o sufixo Propriedade são propriedades associáveis. Se você estiver tentando usar uma propriedade como TextColor em um setter, verifique se há uma propriedade associável correspondente chamada TextColorProperty para esse controle. Na prática, quase todas as propriedades que você vai querer usar em seus setters são implementadas dessa maneira.
O que é um estilo?
Um estilo é uma coleção de setters direcionados a um tipo específico de controle. O .NET MAUI exige o tipo de destino para que possa garantir que as propriedades em seus setters existem nesse tipo.
O código a seguir mostra um estilo que combina os quatro valores do exemplo anterior. Observe que TargetType está definido como Button e todas as propriedades nos setters são membros da classe Button. Você não pode usar esse estilo para um rótulo, porque a classe Label não inclui a propriedade BorderColor ou BorderWidth.
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="#2A84D3" />
<Setter Property="BorderColor" Value="#1C5F9B" />
<Setter Property="BorderWidth" Value="3" />
<Setter Property="TextColor" Value="White" />
</Style>
Definir um estilo
Normalmente, você define estilos como recursos dentro de um objeto ResourceDictionary. Um dicionário de recursos torna fácil usar o estilo entre vários controles na mesma página ou até mesmo em todo o aplicativo. O código a seguir mostra como definir um estilo como um recurso dentro de um dicionário. Observe que o estilo recebe um nome usando a propriedade x:Key. Nomear um estilo permite que você faça referência a ele de dentro de suas páginas XAML.
<ContentPage.Resources>
<Style x:Key="MyButtonStyle" TargetType="Button">
...
</Style>
</ContentPage.Resources>
Aplicar um estilo
Você anexa um estilo a um controle atribuindo o nome à propriedade Style. A atribuição faz com que cada um dos objetos Setter no estilo seja aplicado ao controle de destino. O código a seguir mostra como aplicar nosso estilo de botão a dois botões.
<Button Text="OK" Style="{StaticResource MyButtonStyle}" />
<Button Text="Cancel" Style="{StaticResource MyButtonStyle}" />
No exemplo anterior, você usou a extensão de marcação StaticResource para anexar o estilo aos controles. Essa técnica é ótima quando você não precisa que o estilo mude no runtime. Mas e se você quiser implementar algo como temas dinâmicos em que a interface do usuário precisa mudar? Nesse caso, você pode usar a extensão de marcação DynamicResource para carregar o estilo.
<Button Text="Cancel" Style="{DynamicResource MyButtonStyle}" />
O DynamicResource escuta a substituição da propriedade x:Key no dicionário de recursos. Se você escrever um código que carrega um novo estilo no ResourceDictionary com o mesmo valor x:Key, o novo estilo será aplicado automaticamente à interface do usuário.
Usar um estilo implícito para vários controles
Suponha que sua interface do usuário tenha 50 botões e você queira aplicar o mesmo estilo a todos eles. Com o que sabemos até agora, você precisará atribuir à propriedade Style em cada botão manualmente. Isso não é tão difícil de fazer, mas ainda é entediante.
Um estilo implícito é um estilo que você adiciona a um dicionário de recursos sem dar a ele um identificador x:Key. Estilos implícitos são aplicados automaticamente a todos os controles do objeto TargetType.
O código a seguir mostra o exemplo anterior declarado como um estilo implícito. Esse estilo é aplicado a todos os botões da página.
<ContentPage.Resources>
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="BorderColor" Value="Navy" />
...
</Style>
</ContentPage.Resources>
Importante
A correspondência dos estilos implícitos para controles requer uma correspondência exata com o TargetType especificado. Os controles herdados do tipo de destino não receberão os estilos. Para afetar controles herdados, você poderá definir o atributo Style.ApplyToDerivedTypes como True ao definir o estilo. Por exemplo, para aplicar um estilo ao tipo Button e fazer com que ele afete qualquer um dos botões que herdam de Button (como um ImageButton, RadioButton ou um tipo personalizado criado), você poderá usar um estilo como este.
<ContentPage.Resources>
<Style TargetType="Button"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor" Value="Black" />
</Style>
</ContentPage.Resources>
Substituir um estilo
Pense em um estilo como o fornecimento de um conjunto de valores padrão para controles. Um estilo existente pode estar próximo de seus requisitos, mas conter um ou dois setters que você não deseja. Nesse caso, você pode aplicar o estilo e, em seguida, substituir o valor definindo as propriedades diretamente. A configuração explícita é aplicada após o estilo e, portanto, substitui o valor do estilo.
Suponha que você queira usar o estilo a seguir para vários botões na sua página.
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="BorderRadius" Value="10" />
<Setter Property="BorderWidth" Value="3" />
</Style>
Este estilo funciona para todos os seus botões, com a exceção de Cancelar, que precisa de uma tela de fundo vermelha. Você pode usar o mesmo estilo para o botão Cancelar, desde que também defina a propriedade BackgroundColor diretamente. O código a seguir mostra como substituir a configuração de cor.
<Button
Text="Cancel"
Style="{StaticResource MyButtonStyle}"
BackgroundColor="Red"
... />
Definir um tipo de ancestral como destino
Suponha que você queira uma cor da tela de fundo personalizada para seus botões e rótulos. Você pode criar estilos separados para cada tipo ou criar um estilo com TargetType definido como VisualElement. Essa técnica funciona porque VisualElement é uma classe base para Button e Label.
O código a seguir mostra um estilo que tem como destino uma classe base que está sendo aplicada a dois tipos diferentes de derivada.
<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
<Setter Property="BackgroundColor" Value="#2A84D3" />
</Style>
...
<Button Style="{StaticResource MyVisualElementStyle}" ... />
<Label Style="{StaticResource MyVisualElementStyle}" ... />
Este exemplo identifica o estilo usando x:Key e os controles o aplicam explicitamente. Um estilo implícito não funciona aqui porque TargetType para um estilo implícito deve ser uma correspondência exata com o tipo de controle.
Usar BasedOn para herdar de um estilo
Suponha que você queira criar uma aparência consistente para sua interface do usuário. Você decide que todos os controles devem usar uma cor da tela de fundo consistente. É provável que a configuração de cor da tela de fundo apareça em mais de um de seus estilos. O código a seguir mostra dois estilos com um setter repetido.
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="BorderColor" Value="Navy" />
<Setter Property="BorderWidth" Value="5" />
</Style>
<Style x:Key="MyEntryStyle" TargetType="Entry">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="TextColor" Value="White" />
</Style>
Você pode usar a herança de estilo para criar o setter duplicado em um estilo base. Para criar um estilo derivado, defina sua propriedade BasedOn para fazer referência ao estilo base. O novo estilo herda todos os setters de seu estilo base. O estilo derivado também pode adicionar novos setters ou substituir um setter herdado por um contendo um valor diferente.
O código a seguir mostra os estilos do exemplo anterior refatorados em uma hierarquia. O setter comum aparece somente no estilo base, em vez de ser repetido. Observe que você usa a extensão de marcação StaticResource para pesquisar o estilo base. Você não pode usar DynamicResource nessa situação.
<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
<Setter Property="BackgroundColor" Value="Blue" />
</Style>
<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource MyVisualElementStyle}">
<Setter Property="BorderColor" Value="Navy" />
<Setter Property="BorderWidth" Value="5" />
</Style>
<Style x:Key="MyEntryStyle" TargetType="Entry" BasedOn="{StaticResource MyVisualElementStyle}">
<Setter Property="TextColor" Value="White" />
</Style>
O valor TargetType do estilo base e dos estilos derivados precisam ser compatíveis. Para que os estilos sejam compatíveis, eles devem ter a mesma propriedade TargetType ou o TargetType do estilo derivado deve ser um descendente do TargetType do estilo base.