Стили представляют набор свойств и их значений, которые могут применяться к элементам. Основная задача стилей - создать стилевое единообразие для элементов интерфейса. Стили хранятся в ресурсах и отделяют стилизацию элементов от пользовательского интерфейса.
Чтобы понять, как стили упрощают нам работу, рассмотрим простой пример:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <StackLayout Padding="20"> <Button Text="iOS" TextColor="#004D40" BackgroundColor="#80CBC4" Margin="10" /> <Button Text="Android" TextColor="#004D40" BackgroundColor="#80CBC4" Margin="10" /> </StackLayout> </ContentPage>
Здесь определены две кнопки, которые фактически имеют один и тот же стиль: одни и те же цвет фона и текста, а также размер внешних отступов. Единственное отличие состоит в тексте кнопки.
Однако в данном случае мы вынуждены повторяться и повторно определять один и те же свойства и одни и те же значения для каждого из элементов.
Теперь применим стили:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="buttonStyle" TargetType="Button"> <Setter Property="TextColor" Value="#004D40" /> <Setter Property="BackgroundColor" Value="#80CBC4" /> <Setter Property="Margin" Value="10" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout Padding="20"> <Button Text="iOS" Style="{StaticResource buttonStyle}" /> <Button Text="Android" Style="{StaticResource buttonStyle}" /> </StackLayout> </ContentPage>
Стиль создается как ресурс с помощью объекта Style и, как любой другой ресурс, он обязательно должен иметь ключ. Атрибут TargetType
указывает, к какому типу оносится стиль. В данном случае это тип Button
.
С помощью коллекции Setters определяется группа свойств, входящих в стиль. В нее входят объекты Setter, которые имеют следующие свойства:
Property: указывает на свойство, к которому будет применять данный сеттер. При этом свойство должно представлять тип BindableProperty
Value: собственно значение свойства
Поскольку стиль определяется как ресурс, то для его установки используются расширения StaticResource или DynamicResource (если стиль динамический):
<Button Text="iOS" Style="{StaticResource buttonStyle}" /> <Button Text="Android" Style="{DynamicResource buttonStyle}" />
Иногда свойство может представлять сложный объект, либо же значение формируется сложным способом. Например, у класса Color есть конструктор,
который принимет три значения int
для трех составляющих цвет: красной, зеленой и синей компоненты. В этом случае мы можем расписать формирование объекта:
<Style x:Key="buttonStyle" TargetType="Button"> <Setter Property="TextColor"> <Setter.Value> <Color> <x:Arguments> <x:Int32>0</x:Int32> <x:Int32>75</x:Int32> <x:Int32>25</x:Int32> </x:Arguments> </Color> </Setter.Value> </Setter> <Setter Property="BackgroundColor" Value="#80CBC4" /> <Setter Property="Margin" Value="10" /> </Style>
Также в качестве значения можно устанавливать ссылку на другой ресурс:
<ContentPage.Resources> <ResourceDictionary> <Color x:Key="greenColor">#004D40</Color> <Style x:Key="buttonStyle" TargetType="Button"> <Setter Property="TextColor" Value="{StaticResource Key=greenColor}" /> <Setter Property="BackgroundColor" Value="#80CBC4" /> <Setter Property="Margin" Value="10" /> </Style> </ResourceDictionary> </ContentPage.Resources>
Если нам надо создать общий стиль для элементов определенного типа, то можно не задавать ключ ресурса, а достаточно установить у стиля атрибут TargetType, в который передается тип элементов:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <Style TargetType="Button"> <Setter Property="TextColor" Value="#004D40" /> <Setter Property="BackgroundColor" Value="#80CBC4" /> <Setter Property="Margin" Value="10" /> </Style> </ContentPage.Resources> <StackLayout Padding="20"> <Button Text="iOS" /> <Button Text="Android" /> </StackLayout> </ContentPage>
Теперь у кнопок не надо будет указывать ресурс стиля, так как стиль будет автоматически применяться ко всем объектам типа, который указан в атрибуте TargetType.
Стиль позволяет задать некоторые начальные значения. Однако элемент может переопределить отдельные значения из стиля:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <Style x:Key="buttonStyle" TargetType="Button"> <Setter Property="TextColor" Value="#004D40" /> <Setter Property="BackgroundColor" Value="#80CBC4" /> <Setter Property="Margin" Value="10" /> </Style> </ContentPage.Resources> <StackLayout Padding="20"> <Button Text="iOS" Style="{StaticResource buttonStyle}" /> <Button Text="Android" Style="{StaticResource buttonStyle}" BackgroundColor="#B2EBF2" /> </StackLayout> </ContentPage>
В данном случае кнопка получает все значения из стиля buttonStyle, однако переопределяет цвет текста, так как прямое использование атрибутов элемента имеет приоритет над применяемым стилем.
Для создания стиля в коде используется объект Style:
namespace HelloApp { class StartPage : ContentPage { public StartPage() { Style buttonStyle = new Style(typeof(Button)) { Setters = { new Setter { Property = Button.TextColorProperty, Value = Color.FromArgb("#004D40") }, new Setter { Property = Button.BackgroundColorProperty, Value = Color.FromArgb("#80CBC4") }, new Setter { Property = Button.MarginProperty, Value = 10 } } }; Button button1 = new Button { Text = "iOS", Style = buttonStyle }; Button button2 = new Button { Text = "Android", Style = buttonStyle }; Content = new StackLayout { Padding = 20, Children = { button1, button2 } }; } } }
В конструктор объекта Style передается тип, для которого предназначен данный стиль - аналогично использованию атрибута TargetType в XAML.
При создании стиля в коде следует учитывать, что в качестве свойств указываются именно BindableProperty (как правило называется по имени обычного свойства с суффиксом Property). Например:
Property = Button.TextColorProperty
А не просто TextColor. Причем в начале идет тип (в данном случае Button), а потом идет название свойства (здесь TextColorProperty).
С помощью свойства BasedOn можно наследовать один стиль от другого. Например:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="baseButtonStyle" TargetType="Button"> <Setter Property="Margin" Value="10" /> <Setter Property="WidthRequest" Value="120" /> <Setter Property="TextColor" Value="#01579B" /> <Setter Property="BackgroundColor" Value="#fff" /> </Style> <Style x:Key="greenButtonStyle" TargetType="Button" BasedOn="{StaticResource baseButtonStyle}"> <Setter Property="TextColor" Value="#004D40" /> <Setter Property="BackgroundColor" Value="#80CBC4" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout Padding="20"> <Button Text="iOS" Style="{StaticResource baseButtonStyle}" /> <Button Text="Android" Style="{StaticResource greenButtonStyle}" /> </StackLayout> </ContentPage>
Здесь у стиля greenButtonStyle
атрибут BasedOn
указывает на другой стиль baseButtonStyle
. И таким образом,
стиль greenButtonStyle будет перенимать все установки от baseButtonStyle. При этом наследующий стиль может переопределить значения из наследуемого. В частости, здесь переопределяется
значение свойства TextColor и BackgroundColor.
При наследовании стилей важно, чтобы тип элементов, указанный в качестве значения атрибута TargetType, совпадал. Например, в данном случае оба стиля применяется к элементам типа Button.
Наследование в коде C# осуществляется с помощью установки у стиля свойства BasedOn:
Style basedStyle = new Style(typeof(Button)); Style childStyle = new Style(typeof(Button)) { BasedOn = basedStyle };
По умолчанию проект .NET MAUI уже содержит ряд встроенных стилей. Их можно найти в файле Styles.xaml в папке Resources/Styles:
Эти стили подключаются в качестве глобальных ресурсов в файле App.xaml и предоставляют базую стилизацию для некоторых элементов.