Xamarin.Forms dicionários de recursos

Baixar exemplo Baixar o exemplo

Um ResourceDictionary é um repositório para recursos usados por um Xamarin.Forms aplicativo. Os recursos típicos armazenados em um ResourceDictionary incluem estilos, modelos de controle, modelos de dados, cores e conversores.

No XAML, os recursos armazenados em um ResourceDictionary podem ser referenciados e aplicados a elementos usando a StaticResource extensão de marcação ou DynamicResource . Em C#, os recursos também podem ser definidos em um ResourceDictionary e, em seguida, referenciados e aplicados a elementos usando um indexador baseado em cadeia de caracteres. No entanto, há pouca vantagem em usar um ResourceDictionary em C#, pois objetos compartilhados podem ser armazenados como campos ou propriedades e acessados diretamente sem precisar recuperá-los primeiro de um dicionário.

Criar recursos no XAML

Cada VisualElement objeto derivado tem uma Resources propriedade , que é uma ResourceDictionary que pode conter recursos. Da mesma forma, um Application objeto derivado tem uma Resources propriedade , que é uma ResourceDictionary que pode conter recursos.

Um Xamarin.Forms aplicativo contém apenas a classe derivada de Application, mas geralmente usa muitas classes derivadas de VisualElement, incluindo páginas, layouts e controles. Qualquer um desses objetos pode ter sua Resources propriedade definida como um ResourceDictionary que contém recursos. Escolhendo onde colocar determinados ResourceDictionary impactos em que os recursos podem ser usados:

  • Recursos em um ResourceDictionary anexado a uma exibição como Button ou Label que só podem ser aplicados a esse objeto específico.
  • Recursos em um ResourceDictionary anexado a um layout como StackLayout ou Grid podem ser aplicados ao layout e a todos os filhos desse layout.
  • Os recursos em um ResourceDictionary definido no nível da página podem ser aplicados à página e a todos os seus filhos.
  • Os recursos em um ResourceDictionary definido no nível do aplicativo podem ser aplicados em todo o aplicativo.

Com exceção de estilos implícitos, cada recurso no dicionário de recursos deve ter uma chave de cadeia de caracteres exclusiva definida com o x:Key atributo .

O XAML a seguir mostra os recursos definidos em um nível ResourceDictionary de aplicativo no arquivo 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>

Neste exemplo, o dicionário de recursos define um Thickness recurso, vários Color recursos e dois recursos implícitos Style . Para obter mais informações sobre a App classe , consulte Classe de aplicativoXamarin.Forms.

Observação

Também é válido colocar todos os recursos entre marcas explícitas ResourceDictionary . No entanto, como Xamarin.Forms 3.0, as ResourceDictionary marcas não são necessárias. Em vez disso, o ResourceDictionary objeto é criado automaticamente e você pode inserir os recursos diretamente entre as Resources marcas de elemento de propriedade.

Consumir recursos em XAML

Cada recurso tem uma chave especificada usando o x:Key atributo , que se torna sua chave de dicionário no ResourceDictionary. A chave é usada para fazer referência a um recurso do ResourceDictionary com a StaticResource extensão de marcação ou DynamicResource .

A StaticResource extensão de marcação é semelhante à DynamicResource extensão de marcação em que ambos usam uma chave de dicionário para fazer referência a um valor de um dicionário de recursos. No entanto, enquanto a StaticResource extensão de marcação executa uma única pesquisa de dicionário, a DynamicResource extensão de marcação mantém um link para a chave de dicionário. Portanto, se a entrada de dicionário associada à chave for substituída, a alteração será aplicada ao elemento visual. Isso permite que alterações de recursos de runtime sejam feitas em um aplicativo. Para obter mais informações sobre extensões de marcação, consulte Extensões de marcação XAML.

O exemplo XAML a seguir mostra como consumir recursos e também define recursos adicionais em um 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>

Neste exemplo, o ContentPage objeto consome o estilo implícito definido no dicionário de recursos no nível do aplicativo. O StackLayout objeto consome o PageMargin recurso definido no dicionário de recursos no nível do aplicativo, enquanto o Button objeto consome o estilo implícito definido no StackLayout dicionário de recursos. Isso resulta na aparência mostrada nas capturas de tela seguir:

consumindo recursos resourceDictionary

Importante

Os recursos específicos de uma única página não devem ser incluídos em um dicionário de recursos no nível do aplicativo, pois esses recursos serão analisados na inicialização do aplicativo, em vez de quando exigidos por uma página. Para obter mais informações, consulte Reduzir o tamanho do dicionário de recursos do aplicativo.

Comportamento de pesquisa de recursos

O seguinte processo de pesquisa ocorre quando um recurso é referenciado com a StaticResource extensão de marcação ou DynamicResource :

  • A chave solicitada é verificada no dicionário de recursos, se existir, para o elemento que define a propriedade. Se a chave solicitada for encontrada, seu valor será retornado e o processo de pesquisa será encerrado.
  • Se uma correspondência não for encontrada, o processo de pesquisa pesquisa a árvore visual para cima, verificando o dicionário de recursos de cada elemento pai. Se a chave solicitada for encontrada, seu valor será retornado e o processo de pesquisa será encerrado. Caso contrário, o processo continuará para cima até que o elemento raiz seja atingido.
  • Se uma correspondência não for encontrada no elemento raiz, o dicionário de recursos no nível do aplicativo será examinado.
  • Se uma correspondência ainda não for encontrada, uma XamlParseException será lançada.

Portanto, quando o analisador XAML encontra uma StaticResource extensão ou DynamicResource marcação, ele procura uma chave correspondente viajando pela árvore visual, usando a primeira correspondência encontrada. Se essa pesquisa terminar na página e a chave ainda não tiver sido encontrada, o analisador XAML pesquisará o ResourceDictionary anexado ao App objeto . Se a chave ainda não for encontrada, uma exceção será gerada.

Substituir recursos

Quando os recursos compartilham chaves, os recursos definidos mais baixos na árvore visual terão precedência sobre aqueles definidos mais acima. Por exemplo, definir um AppBackgroundColor recurso como AliceBlue no nível do aplicativo será substituído por um recurso de nível AppBackgroundColor de página definido como Teal. Da mesma forma, um recurso de nível AppBackgroundColor de página será substituído por um recurso de nível AppBackgroundColor de controle.

Dicionários de recursos autônomos

Uma classe derivada de ResourceDictionary também pode estar em um arquivo XAML autônomo. Em seguida, o arquivo XAML pode ser compartilhado entre aplicativos.

Para criar esse arquivo, adicione um novo item de Exibição de Conteúdo ou Página de Conteúdo ao projeto (mas não uma Exibição de Conteúdo ou Página de Conteúdo com apenas um arquivo C#). Exclua o arquivo code-behind e, no arquivo XAML, altere o nome da classe base de ContentView ou ContentPage para ResourceDictionary. Além disso, remova o x:Class atributo da marca raiz do arquivo.

O exemplo XAML a seguir mostra um ResourceDictionary chamado 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>

Neste exemplo, o ResourceDictionary contém um único recurso, que é um objeto do tipo DataTemplate. MyResourceDictionary.xaml pode ser consumido mesclando-o em outro dicionário de recursos.

Por padrão, o vinculador removerá arquivos XAML autônomos de builds de versão quando o comportamento do vinculador for definido para vincular todos os assemblies. Para garantir que os arquivos XAML autônomos permaneçam em um build de versão:

  1. Adicione um atributo personalizado Preserve ao assembly que contém os arquivos XAML autônomos. Para obter mais informações, consulte Preservando o código.

  2. Defina o Preserve atributo no nível do assembly:

    [assembly:Preserve(AllMembers = true)]
    

Para obter mais informações sobre a vinculação, consulte Vinculando aplicativos Xamarin.iOS e Vinculando no Android.

Dicionários de recursos mesclados

Dicionários de recursos mesclados combinam um ou mais ResourceDictionary objetos em outro ResourceDictionary.

Mesclar dicionários de recursos locais

Um arquivo local ResourceDictionary pode ser mesclado em outro ResourceDictionary criando um ResourceDictionary objeto cuja Source propriedade é definida como o nome do arquivo XAML com os recursos:

<ContentPage ...>
    <ContentPage.Resources>
        <!-- Add more resources here -->
        <ResourceDictionary Source="MyResourceDictionary.xaml" />
        <!-- Add more resources here -->
    </ContentPage.Resources>
    ...
</ContentPage>

Essa sintaxe não cria uma instância da MyResourceDictionary classe . Em vez disso, ele faz referência ao arquivo XAML. Por esse motivo, ao definir a Source propriedade, um arquivo code-behind não é necessário e o x:Class atributo pode ser removido da marca raiz do arquivo MyResourceDictionary.xaml .

Importante

A Source propriedade só pode ser definida a partir de XAML.

Mesclar dicionários de recursos de outros assemblies

Um ResourceDictionary também pode ser mesclado em outro ResourceDictionary adicionando-o à MergedDictionaries propriedade do ResourceDictionary. Essa técnica permite que dicionários de recursos sejam mesclados, independentemente do assembly no qual residem. Mesclar dicionários de recursos de assemblies externos requer que a ResourceDictionary ação de build seja definida como EmbeddedResource, ter um arquivo code-behind e definir o x:Class atributo na marca raiz do arquivo.

Aviso

A classe ResourceDictionary também define uma propriedade MergedWith. No entanto, essa propriedade foi preterida e não deve mais ser usada.

O exemplo de código a seguir mostra dois dicionários de recursos sendo adicionados à MergedDictionaries coleção de um nível ResourceDictionaryde página:

<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>

Neste exemplo, um dicionário de recursos do mesmo assembly e um dicionário de recursos de um assembly externo são mesclados no dicionário de recursos no nível da página. Além disso, você também pode adicionar outros ResourceDictionary objetos dentro das MergedDictionaries marcas de elemento de propriedade e outros recursos fora dessas marcas.

Importante

Pode haver apenas uma MergedDictionaries marca de elemento de propriedade em um ResourceDictionary, mas você pode colocar quantos ResourceDictionary objetos lá forem necessários.

Quando recursos mesclados ResourceDictionary compartilham valores de atributo idênticos x:Key , Xamarin.Forms usa a seguinte precedência de recurso:

  1. Os recursos locais para o dicionário de recursos.
  2. Os recursos contidos nos dicionários de recursos que foram mesclados por meio da MergedDictionaries coleção, na ordem inversa, são listados na MergedDictionaries propriedade .

Observação

Pesquisar dicionários de recursos pode ser uma tarefa com uso intensivo de computação se um aplicativo contiver vários dicionários de recursos grandes. Portanto, para evitar pesquisas desnecessárias, você deve garantir que cada página em um aplicativo use apenas dicionários de recursos apropriados para a página.

Encontre mais vídeos sobre o Xamarin no Channel 9 e no YouTube.