Xamarin.Forms словари ресурсов
A ResourceDictionary
— это репозиторий для ресурсов, используемых приложением Xamarin.Forms . Типичные ресурсы, хранящиеся в ResourceDictionary
стилях, шаблонах элементов управления, шаблонах данных, цветах и преобразователях.
В XAML ресурсы, хранящиеся в объекте ResourceDictionary
, можно ссылаться и применять к элементам с помощью StaticResource
расширения разметки или DynamicResource
разметки. В C#ресурсы также можно определить в объекте ResourceDictionary
, а затем ссылаться и применяться к элементам с помощью индексатора на основе строк. Однако в C#мало преимуществ ResourceDictionary
, так как общие объекты могут храниться в виде полей или свойств и обращаться напрямую без необходимости получить их из словаря.
Создание ресурсов в XAML
Каждый VisualElement
производный Resources
объект имеет свойство, которое может ResourceDictionary
содержать ресурсы. Аналогичным образом производный Application
Resources
объект имеет свойство, которое может ResourceDictionary
содержать ресурсы.
Приложение Xamarin.Forms содержит только класс, производный от , но часто использует многие классы, производные от Application
VisualElement
страниц, макетов и элементов управления. Любой из этих объектов может иметь значение свойства Resources
, ResourceDictionary
содержащего ресурсы. Выбор места для конкретного ResourceDictionary
воздействия, в котором можно использовать ресурсы:
- Ресурсы,
ResourceDictionary
подключенные к представлению, напримерButton
илиLabel
могут применяться только к конкретному объекту. - Ресурсы в присоединенном
ResourceDictionary
к макету, напримерStackLayout
Grid
или могут применяться к макету и всем дочерним элементам этого макета. - Ресурсы, определенные на
ResourceDictionary
уровне страницы, можно применять к странице и ко всем его дочерним элементам. - Ресурсы, определенные на
ResourceDictionary
уровне приложения, могут применяться во всем приложении.
За исключением неявных стилей, каждый ресурс в словаре ресурсов должен иметь уникальный строковый ключ, определенный атрибутом x:Key
.
В следующем XAML показаны ресурсы, определенные на уровне ResourceDictionary
приложения в файле App.xaml :
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.App">
<Application.Resources>
<Thickness x:Key="PageMargin">20</Thickness>
<!-- Colors -->
<Color x:Key="AppBackgroundColor">AliceBlue</Color>
<Color x:Key="NavigationBarColor">#1976D2</Color>
<Color x:Key="NavigationBarTextColor">White</Color>
<Color x:Key="NormalTextColor">Black</Color>
<!-- Implicit styles -->
<Style TargetType="{x:Type NavigationPage}">
<Setter Property="BarBackgroundColor"
Value="{StaticResource NavigationBarColor}" />
<Setter Property="BarTextColor"
Value="{StaticResource NavigationBarTextColor}" />
</Style>
<Style TargetType="{x:Type ContentPage}"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</Application.Resources>
</Application>
В этом примере словарь ресурсов определяет Thickness
ресурс, несколько Color
ресурсов и два неявных Style
ресурса. Дополнительные сведения о классе см. в разделе Xamarin.Forms "Класс приложенийApp
".
Примечание.
Кроме того, можно разместить все ресурсы между явными ResourceDictionary
тегами. Однако, так как Xamarin.Forms теги 3.0 ResourceDictionary
не требуются. Вместо этого ResourceDictionary
объект создается автоматически, и вы можете вставить ресурсы непосредственно между Resources
тегами элемента свойства.
Использование ресурсов в XAML
Каждый ресурс имеет ключ, указанный с помощью атрибута x:Key
, который становится его ключом словаря в элементе ResourceDictionary
. Ключ используется для ссылки на ресурс из ResourceDictionary
StaticResource
расширения разметки или DynamicResource
расширения разметки.
StaticResource
Расширение разметки аналогично DynamicResource
расширению разметки в том, что оба используют ключ словаря для ссылки на значение из словаря ресурсов. Однако в то время как StaticResource
расширение разметки выполняет поиск одного словаря, DynamicResource
расширение разметки сохраняет ссылку на ключ словаря. Поэтому при замене записи словаря, связанной с ключом, изменение применяется к визуальному элементу. Это позволяет вносить изменения ресурсов среды выполнения в приложение. Дополнительные сведения о расширениях разметки см. в разделе "Расширения разметки XAML".
В следующем примере XAML показано, как потреблять ресурсы, а также определять дополнительные ресурсы в StackLayout
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.HomePage"
Title="Home Page">
<StackLayout Margin="{StaticResource PageMargin}">
<StackLayout.Resources>
<!-- Implicit style -->
<Style TargetType="Button">
<Setter Property="FontSize" Value="Medium" />
<Setter Property="BackgroundColor" Value="#1976D2" />
<Setter Property="TextColor" Value="White" />
<Setter Property="CornerRadius" Value="5" />
</Style>
</StackLayout.Resources>
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries." />
<Button Text="Navigate"
Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage>
В этом примере объект использует неявный стиль, ContentPage
определенный в словаре ресурсов уровня приложения. Объект StackLayout
использует ресурс, определенный в словаре ресурсов уровня приложения, а Button
объект использует PageMargin
неявный стиль, определенный в StackLayout
словаре ресурсов. Результат показан на следующих снимках экрана:
Внимание
Ресурсы, относящиеся к одной странице, не должны быть включены в словарь ресурсов уровня приложения, так как такие ресурсы затем будут проанализированы при запуске приложения, а не при необходимости на странице. Дополнительные сведения см. в разделе "Уменьшить размер словаря ресурсов приложения".
Поведение подстановки ресурсов
Следующий процесс подстановки возникает, когда ресурс ссылается на StaticResource
расширение разметки или DynamicResource
разметки:
- Запрошенный ключ проверяется в словаре ресурсов, если он существует, для элемента, который задает свойство. Если запрошенный ключ найден, возвращается его значение, а процесс подстановки завершается.
- Если совпадение не найдено, процесс подстановки выполняет поиск визуального дерева вверх, проверяя словарь ресурсов каждого родительского элемента. Если запрошенный ключ найден, возвращается его значение, а процесс подстановки завершается. В противном случае процесс продолжается вверх до достижения корневого элемента.
- Если совпадение не найдено в корневом элементе, проверяется словарь ресурсов уровня приложения.
- Если совпадение по-прежнему не найдено,
XamlParseException
создается исключение.
Таким образом, когда средство синтаксического анализа XAML обнаруживает StaticResource
расширение разметки или DynamicResource
выполняет поиск соответствующего ключа, перемещаясь по визуальному дереву, используя первое совпадение. Если этот поиск заканчивается на странице, а ключ еще не найден, средство синтаксического анализа XAML выполняет поиск ResourceDictionary
присоединенного к объекту App
. Если ключ по-прежнему не найден, создается исключение.
Переопределение ресурсов
Когда ресурсы используют ключи общего доступа, ресурсы, определенные ниже в визуальном дереве, будут иметь приоритет над теми, которые определены выше. Например, задание AppBackgroundColor
ресурса AliceBlue
на уровне приложения переопределяется набором Teal
ресурсов уровня AppBackgroundColor
страницы. Аналогичным образом ресурс уровня страницы переопределяется ресурсом уровня AppBackgroundColor
AppBackgroundColor
управления.
автономные словари ресурсов
Класс, производный от ResourceDictionary
него, также может находиться в автономном XAML-файле. Затем ФАЙЛ XAML можно совместно использовать между приложениями.
Чтобы создать такой файл, добавьте новый элемент представления содержимого или страницы контента в проект (но не страницу содержимого или страницу содержимого только с файлом C#). Удалите файл программной части, а в XAML-файле измените имя базового класса с ContentView
или ContentPage
на ResourceDictionary
. Кроме того, удалите x:Class
атрибут из корневого тега файла.
В следующем примере XAML показан именованный ResourceDictionary
MyResourceDictionary.xaml:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<DataTemplate x:Key="PersonDataTemplate">
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
TextColor="{StaticResource NormalTextColor}"
FontAttributes="Bold" />
<Label Grid.Column="1"
Text="{Binding Age}"
TextColor="{StaticResource NormalTextColor}" />
<Label Grid.Column="2"
Text="{Binding Location}"
TextColor="{StaticResource NormalTextColor}"
HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
В этом примере ResourceDictionary
содержит один ресурс, который является объектом типа DataTemplate
. MyResourceDictionary.xaml можно использовать путем объединения его в другой словарь ресурсов.
По умолчанию компоновщик удаляет автономные файлы XAML из сборок выпуска, когда поведение компоновщика настроено для связывания всех сборок. Чтобы убедиться, что автономные ФАЙЛЫ XAML остаются в сборке выпуска:
Добавьте настраиваемый
Preserve
атрибут в сборку, содержащую автономные ФАЙЛЫ XAML. Дополнительные сведения см. в разделе "Сохранение кода".Preserve
Задайте атрибут на уровне сборки:[assembly:Preserve(AllMembers = true)]
Дополнительные сведения о связывании см. в разделе "Связывание приложений Xamarin.iOS" и "Связывание" в Android.
Объединенные словари ресурсов
Объединенные словари ресурсов объединяют один или несколько ResourceDictionary
объектов в другой ResourceDictionary
.
Слияние словарей локальных ресурсов
Локальный ResourceDictionary
файл можно объединить в другой ResourceDictionary
, создав ResourceDictionary
объект, свойство которого Source
имеет имя файла XAML-файла с ресурсами:
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Этот синтаксис не создает экземпляр MyResourceDictionary
класса. Вместо этого он ссылается на XAML-файл. По этой причине при задании Source
свойства файл программной части не требуется, а x:Class
атрибут можно удалить из корневого тега файла MyResourceDictionary.xaml .
Внимание
Свойство Source
можно задать только из XAML.
Объединение словарей ресурсов из других сборок
Кроме того, можно ResourceDictionary
объединить его в другое ResourceDictionary
MergedDictionaries
, добавив его в свойство объекта ResourceDictionary
. Этот метод позволяет объединять словари ресурсов независимо от сборки, в которой они находятся. Объединение словарей ресурсов из внешних сборок требует ResourceDictionary
наличия действия сборки в EmbeddedResource, наличия файла программной части и определения x:Class
атрибута в корневом теге файла.
Предупреждение
Класс ResourceDictionary
также определяет свойство MergedWith
. Однако это свойство устарело и больше не должно использоваться.
В следующем примере кода показаны два словаря ресурсов, добавляемые в MergedDictionaries
коллекцию уровня ResourceDictionary
страницы:
<ContentPage ...
xmlns:local="clr-namespace:ResourceDictionaryDemo"
xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
<ContentPage.Resources>
<ResourceDictionary>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>
<!-- Add more resource dictionaries here -->
<local:MyResourceDictionary />
<theme:LightTheme />
<!-- Add more resource dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Add more resources here -->
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
В этом примере словарь ресурсов из той же сборки и словарь ресурсов из внешней сборки объединяются в словарь ресурсов уровня страницы. Кроме того, вы также можете добавить другие ResourceDictionary
объекты в MergedDictionaries
теги элементов свойств и другие ресурсы за пределами этих тегов.
Внимание
В нем может быть только один MergedDictionaries
тег ResourceDictionary
элемента свойства, но можно поместить в нее столько ResourceDictionary
объектов, сколько требуется.
Если объединенные ResourceDictionary
ресурсы используют идентичные x:Key
значения атрибутов, Xamarin.Forms использует следующую приоритетность ресурсов:
- Локальные ресурсы словаря ресурсов.
- Ресурсы, содержащиеся в словарях ресурсов, которые были объединены через
MergedDictionaries
коллекцию, в обратном порядке они перечислены в свойствеMergedDictionaries
.
Примечание.
Поиск словарей ресурсов может быть вычислительно интенсивной задачей, если приложение содержит несколько, больших словарей ресурсов. Поэтому, чтобы избежать ненужных поисков, следует убедиться, что каждая страница в приложении использует только словари ресурсов, соответствующие странице.
Дополнительные ссылки
- Расширения разметки XAML
- Стили Xamarin.Forms
- Связывание приложений Xamarin.iOS
- Linking on Android (Компоновка на Android)
- ResourceDictionary API