Создание согласованного пользовательского интерфейса с помощью стилей
- 8 мин
В многоплатформенный пользовательский интерфейс приложения .NET (MAUI) ресурсы отлично подходят для предотвращения жестко закодированных, повторяющихся значений в разметке языка разметки расширяемых приложений (XAML), но они могут быть утомительными для применения. Каждое значение свойства нужно назначать отдельно, и это загромождает код XAML. В этом уроке показано, как сгруппировать несколько параметров в стиль, чтобы код смотрелся чище и его было удобнее обслуживать.
Как ресурсы загромождают XAML
Ресурс предоставляет значение для одного свойства. Но использование большого количества ресурсов может загромождать код XAML. Предположим, вы хотите настроить внешний вид кнопок. Сначала вы создаете ресурсы для нужных значений. Затем вы применяете каждый ресурс ко всем кнопкам. В следующем коде показано, как может выглядеть разметка XAML для двух обычных кнопок.
<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}" />
Обратите внимание на то, как для всех кнопок задаются одинаковые пять свойств. Использование ресурсов удаляет необходимость повторяющихся жестко закодированных значений в четырех из них. Но такую разметку XAML очень быстро станет трудно читать. Кроме того, если вы настраиваете большое количество свойств для каждого элемента управления, вам будет легко ошибиться и упустить одно из них, что приведет к несогласованности внешнего вида элементов управления. Поэтому можно создать стиль, который присваивает все пять свойств за один раз.
Что такое метод задания?
Сеттеры — это ключевые компоненты, которые вы используете для создания стилей.
Метод задания представляет собой контейнер для пары "свойство — значение". Можно представить метод задания как оператор присваивания. Вы указываете, какое свойство нужно назначить и какое значение применить. Обычно объекты Setter создаются в разметке XAML. В следующем примере создается объект Setter для свойства TextColor .
<Setter Property="TextColor" Value="White" />
Для значения в методе задания можно использовать ресурс, как показано в коде ниже. Этот прием отлично подходит в ситуациях, когда нужно использовать то же значение в нескольких методах задания.
<Setter Property="TextColor" Value="{StaticResource textColor}" />
Примечание.
Значение свойства, которое вы указываете в методе задания, должно быть реализовано как привязываемое свойство. Все свойства элементов управления в .NET MAUI, которые заканчиваются суффиксом Property, являются привязываемыми свойствами. Если вы пытаетесь использовать свойство, например TextColor, в сеттере, убедитесь, что для этого элемента управления есть соответствующее привязываемое свойство под названием TextColorProperty. На практике практически все свойства, которые вы хотите использовать в наборах, реализуются таким образом.
Что такое стиль?
Стиль — это коллекция методов задания, предназначенных для определенного типа элемента управления. .NET MAUI требует тип целевого объекта, чтобы гарантировать, что свойства в методах задания существуют для этого типа.
В следующем коде показан стиль, который содержит все четыре значения из предыдущего примера. Обратите внимание, что TargetType установлен в Button, а все свойства в установщиках являются членами класса Button. Этот стиль нельзя использовать для метки, так как класс Label не включает свойство BorderColor или 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>
Определение стиля
Обычно стили определяются как ресурсы в объекте ResourceDictionary . Словарь ресурсов упрощает использование стиля для нескольких элементов управления на одной странице или даже по всему приложению. В коде ниже показано, как определить стиль в качестве ресурса в словаре. Обратите внимание, что стиль присваивается имени с помощью свойства x:Key . Именование стиля позволяет ссылаться на него на страницах XAML.
<ContentPage.Resources>
<Style x:Key="MyButtonStyle" TargetType="Button">
...
</Style>
</ContentPage.Resources>
Применение стиля
Прикрепите стиль к элементу управления, назначив имя свойству Style . Назначение приводит к применению каждого объекта Setter в стиле к целевому элементу управления. Приведенный ниже код показывает, как применить стиль кнопок к двум кнопкам.
<Button Text="OK" Style="{StaticResource MyButtonStyle}" />
<Button Text="Cancel" Style="{StaticResource MyButtonStyle}" />
В предыдущем примере вы использовали расширение разметки StaticResource для присоединения стиля к элементам управления. Это удобный подход, если стиль не нужно изменять во время выполнения. Но что делать, если вы хотите реализовать нечто вроде динамических тем, где пользовательский интерфейс должен изменяться? В этом случае для загрузки стиля можно использовать расширение разметки DynamicResource .
<Button Text="Cancel" Style="{DynamicResource MyButtonStyle}" />
DynamicResource следит за заменой свойства x:Key в словаре ресурсов. При написании кода, который загружает новый стиль в ResourceDictionary с тем же значением x:Key , новый стиль автоматически применяется к пользовательскому интерфейсу.
Использование неявного стиля для нескольких элементов управления
Предположим, в пользовательском интерфейсе 50 кнопок и вы хотите применить к ним одинаковый стиль. Чтобы сделать это, вам нужно вручную назначить свойство Style на каждой кнопке. Это не сложно, но требует времени.
Неявный стиль — это стиль, добавляемый в словарь ресурсов, не предоставляя ему идентификатор x:Key. Неявные стили автоматически применяются ко всем элементам управления указанного объекта TargetType .
В следующем коде стиль из предыдущего примера объявляется как неявный стиль. Этот стиль применяется к каждой кнопке на странице.
<ContentPage.Resources>
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="BorderColor" Value="Navy" />
...
</Style>
</ContentPage.Resources>
Внимание
Сопоставление неявных стилей с элементами управления требует точного соответствия указанному TargetType. Элементы управления, наследуемые от целевого типа, не получают стили. Чтобы повлиять на унаследованные элементы управления, можно задать для атрибута Style.ApplyToDerivedTypesзначение True при определении стиля. Например, чтобы применить стиль к типу button и повлиять на любую из кнопок, наследуемых от Button (например , ImageButton, RadioButton или настраиваемый тип, который вы создаете), можно использовать такой стиль, как это.
<ContentPage.Resources>
<Style TargetType="Button"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor" Value="Black" />
</Style>
</ContentPage.Resources>
Переопределение стиля
Стиль можно представить как набор значений по умолчанию для элементов управления. Существующий стиль может быть близок к вашим требованиям, но содержит один или два набора, которые вы не хотите. В этом случае можно применить стиль, а затем переопределить значение, задав свойства напрямую. Явное задание применяется после стиля, поэтому оно будет переопределять значение из этого стиля.
Предположим, вы хотите использовать следующий стиль для нескольких кнопок на странице.
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="Blue" />
<Setter Property="BorderRadius" Value="10" />
<Setter Property="BorderWidth" Value="3" />
</Style>
Этот стиль подходит для большинства кнопок, кроме кнопки "Отмена", которой нужен красный фон. Вы можете использовать тот же стиль для кнопки "Отмена", если вы также задаете свойство BackgroundColor напрямую. Следующий код показывает, как можно переопределить параметр цвета.
<Button
Text="Cancel"
Style="{StaticResource MyButtonStyle}"
BackgroundColor="Red"
... />
Нацеливание на тип предка
Предположим, вам нужен пользовательский цвет фона для кнопок и меток. Вы можете создать отдельные стили для каждого типа или создать один стиль с TargetType, установленным для VisualElement. Этот метод работает, так как VisualElement является базовым классом как для button , так и для Label.
В коде ниже показан стиль, предназначенный для базового класса, который применяется к двум разным производным типам.
<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
<Setter Property="BackgroundColor" Value="#2A84D3" />
</Style>
...
<Button Style="{StaticResource MyVisualElementStyle}" ... />
<Label Style="{StaticResource MyVisualElementStyle}" ... />
В этом примере определяется стиль с помощью x:Key , а элементы управления применяют его явным образом. Неявный стиль не работает здесь, так как TargetType для неявного стиля должен точно соответствовать типу элемента управления.
Использование BasedOn для наследования от стиля
Предположим, вы хотите создать единый вид пользовательского интерфейса. Вы решили, что все элементы управления должны иметь один цвет фона. Параметр цвета фона, скорее всего, будет отображаться в нескольких стилях. В следующем коде показано два стиля с одинаковым методом задания.
<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>
Можно использовать наследование стилей, чтобы вынести повторяющиеся методы задания в базовый стиль. Чтобы создать производный стиль, задайте для свойства BasedOn ссылку на базовый стиль. Новый стиль наследует все методы задания от своего базового стиля. Производный стиль также может добавлять новые методы задания или заменить унаследованный метод задания другим, с отличным значением.
В следующем коде показаны стили из предыдущего примера, рефакторингованного в иерархию. Общий метод задания появляется только в базовом стиле и не повторяется. Обратите внимание, что для поиска базового стиля используется расширение разметки StaticResource . В этой ситуации нельзя использовать DynamicResource .
<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>
Значение TargetType базового и производного стилей должно быть совместимо. Для совместимости стилей они должны иметь одно и то же свойство TargetType , либо TargetType производного стиля является потомком targetType базового стиля.
Проверка знаний
Обратная связь
Были ли сведения на этой странице полезными?
Нет
Нужна помощь с этой темой?
Хотите попробовать использовать Ask Learn для уточнения или руководства по этой теме?