Xamarin.Forms словари ресурсов

Download Sample Скачайте пример

A ResourceDictionary — это репозиторий для ресурсов, используемых приложением Xamarin.Forms . Типичные ресурсы, хранящиеся в ResourceDictionaryстилях, шаблонах элементов управления, шаблонах данных, цветах и преобразователях.

В XAML ресурсы, хранящиеся в объекте ResourceDictionary , можно ссылаться и применять к элементам с помощью StaticResource расширения разметки или DynamicResource разметки. В C#ресурсы также можно определить в объекте ResourceDictionary , а затем ссылаться и применяться к элементам с помощью индексатора на основе строк. Однако в C#мало преимуществ ResourceDictionary , так как общие объекты могут храниться в виде полей или свойств и обращаться напрямую без необходимости получить их из словаря.

Создание ресурсов в XAML

Каждый VisualElement производный Resources объект имеет свойство, которое может ResourceDictionary содержать ресурсы. Аналогичным образом производный ApplicationResources объект имеет свойство, которое может ResourceDictionary содержать ресурсы.

Приложение Xamarin.Forms содержит только класс, производный от , но часто использует многие классы, производные от ApplicationVisualElementстраниц, макетов и элементов управления. Любой из этих объектов может иметь значение свойства Resources , ResourceDictionary содержащего ресурсы. Выбор места для конкретного ResourceDictionary воздействия, в котором можно использовать ресурсы:

  • Ресурсы, ResourceDictionary подключенные к представлению, например Button или Label могут применяться только к конкретному объекту.
  • Ресурсы в присоединенном ResourceDictionary к макету, например StackLayoutGrid или могут применяться к макету и всем дочерним элементам этого макета.
  • Ресурсы, определенные на 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. Ключ используется для ссылки на ресурс из ResourceDictionaryStaticResource расширения разметки или 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 словаре ресурсов. Результат показан на следующих снимках экрана:

Consuming ResourceDictionary Resources

Внимание

Ресурсы, относящиеся к одной странице, не должны быть включены в словарь ресурсов уровня приложения, так как такие ресурсы затем будут проанализированы при запуске приложения, а не при необходимости на странице. Дополнительные сведения см. в разделе "Уменьшить размер словаря ресурсов приложения".

Поведение подстановки ресурсов

Следующий процесс подстановки возникает, когда ресурс ссылается на StaticResource расширение разметки или DynamicResource разметки:

  • Запрошенный ключ проверка в словаре ресурсов, если он существует, для элемента, задающего свойство. Если запрошенный ключ найден, возвращается его значение, а процесс подстановки завершается.
  • Если совпадение не найдено, процесс подстановки выполняет поиск визуального дерева вверх, проверка словарь ресурсов каждого родительского элемента. Если запрошенный ключ найден, возвращается его значение, а процесс подстановки завершается. В противном случае процесс продолжается вверх до достижения корневого элемента.
  • Если совпадение не найдено в корневом элементе, проверяется словарь ресурсов уровня приложения.
  • Если совпадение по-прежнему не найдено, XamlParseException создается исключение.

Таким образом, когда средство синтаксического анализа XAML обнаруживает StaticResource расширение разметки или DynamicResource выполняет поиск соответствующего ключа, перемещаясь по визуальному дереву, используя первое совпадение. Если этот поиск заканчивается на странице, а ключ еще не найден, средство синтаксического анализа XAML выполняет поиск ResourceDictionary присоединенного к объекту App . Если ключ по-прежнему не найден, создается исключение.

Переопределение ресурсов

Когда ресурсы используют ключи общего доступа, ресурсы, определенные ниже в визуальном дереве, будут иметь приоритет над теми, которые определены выше. Например, задание AppBackgroundColor ресурса AliceBlue на уровне приложения переопределяется набором Tealресурсов уровня AppBackgroundColor страницы. Аналогичным образом ресурс уровня страницы переопределяется ресурсом уровня AppBackgroundColorAppBackgroundColor управления.

автономные словари ресурсов

Класс, производный от ResourceDictionary него, также может находиться в автономном XAML-файле. Затем ФАЙЛ XAML можно совместно использовать между приложениями.

Чтобы создать такой файл, добавьте новый элемент представления содержимого или страницы контента в проект (но не страницу содержимого или страницу содержимого только с файлом C#). Удалите файл программной части, а в XAML-файле измените имя базового класса с ContentView или ContentPage на ResourceDictionary. Кроме того, удалите x:Class атрибут из корневого тега файла.

В следующем примере XAML показан именованный ResourceDictionaryMyResourceDictionary.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 остаются в сборке выпуска:

  1. Добавьте настраиваемый Preserve атрибут в сборку, содержащую автономные ФАЙЛЫ XAML. Дополнительные сведения см. в разделе "Сохранение кода".

  2. 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 объединить его в другое ResourceDictionaryMergedDictionaries , добавив его в свойство объекта 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 использует следующую приоритетность ресурсов:

  1. Локальные ресурсы словаря ресурсов.
  2. Ресурсы, содержащиеся в словарях ресурсов, которые были объединены через MergedDictionaries коллекцию, в обратном порядке они перечислены в свойстве MergedDictionaries .

Примечание.

Поиск словарей ресурсов может быть вычислительно интенсивной задачей, если приложение содержит несколько, больших словарей ресурсов. Поэтому, чтобы избежать ненужных поисков, следует убедиться, что каждая страница в приложении использует только словари ресурсов, соответствующие странице.

Другие видео о Xamarin см. на Channel 9 и YouTube.