Partilhar via


Dicionário de Recursos e referências de recursos XAML

Você pode definir a interface do usuário ou os recursos para seu aplicativo usando XAML. Recursos geralmente são definições de algum objeto que você espera usar mais de uma vez. Para se referir a um recurso XAML posteriormente, especifique uma chave para um recurso que age como seu nome. Você pode fazer referência a um recurso em um aplicativo ou em qualquer página XAML dentro dele. Você pode definir os seus recursos usando um elemento ResourceDictionary do Windows Runtime XAML. Em seguida, podes referir-te aos teus recursos usando a extensão de marcação StaticResource ou a extensão de marcação ThemeResource .

Os elementos XAML que você pode querer declarar com mais frequência como recursos XAML incluem Style, ControlTemplate, componentes de animação e subclasses Brush . Aqui, explicamos como definir um ResourceDictionary e recursos chaveados e como os recursos XAML se relacionam com outros recursos que você define como parte do seu aplicativo ou pacote de aplicativo. Também explicamos recursos avançados do dicionário de recursos, como MergedDictionaries e ThemeDictionaries.

Pré-requisitos

Uma sólida compreensão da marcação XAML. Recomendamos a leitura da visão geral do XAML .

Definir e usar recursos XAML

Recursos XAML são objetos que são referenciados a partir da marcagem mais de uma vez. Os recursos são definidos em um ResourceDictionary, normalmente em um arquivo separado ou na parte superior da página de marcação, como este.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <x:String x:Key="greeting">Hello world</x:String>
        <x:String x:Key="goodbye">Goodbye world</x:String>
    </Page.Resources>

    <TextBlock Text="{StaticResource greeting}" Foreground="Gray" VerticalAlignment="Center"/>
</Page>

Neste exemplo:

  • <Page.Resources>…</Page.Resources> - Define o dicionário de recursos.
  • <x:String> - Define o recurso com a chave "saudação".
  • {StaticResource greeting} - Procura o recurso com a chave "greeting", que é atribuída à propriedade Text do TextBlock.

Observação

Não confunda os conceitos relacionados ao ResourceDictionary com a ação de compilação de recursos , arquivos de recurso (.resw) ou outros "recursos" discutidos no contexto da estruturação do projeto de código que produz o pacote do aplicativo.

Os recursos não precisam ser strings; eles podem ser qualquer objeto compartilhável, como estilos, modelos, pincéis e cores. No entanto, controles, formas e outros FrameworkElements não são compartilháveis, portanto, não podem ser declarados como recursos reutilizáveis. Para saber mais sobre compartilhamento, veja a seção recursos XAML devem ser compartilháveis mais adiante neste tópico.

Aqui, um pincel e uma cadeia de caracteres são declarados como recursos e usados por controles em uma página.

<Page
    x:Class="SpiderMSDN.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <SolidColorBrush x:Key="myFavoriteColor" Color="green"/>
        <x:String x:Key="greeting">Hello world</x:String>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource myFavoriteColor}" Text="{StaticResource greeting}" VerticalAlignment="Top"/>
    <Button Foreground="{StaticResource myFavoriteColor}" Content="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

Todos os recursos precisam ter uma chave. Normalmente, essa chave é uma cadeia de caracteres definida com x:Key="myString". No entanto, existem algumas outras maneiras de especificar uma chave:

  • Estilo e ControlTemplate requerem TargetType, e usarão o TargetType como chave se x:Key não for especificada. Nesse caso, a chave é o objeto Type real, não uma cadeia de caracteres. (Veja exemplos abaixo)
  • recursos de DataTemplate que tenham um TargetType usarão o TargetType como a chave se x:Key não for especificado. Nesse caso, a chave é o objeto Type real, não uma cadeia de caracteres.
  • x:Name pode ser usado em vez de x:Key. No entanto, x:Name também gera um campo de code-behind para o recurso. Como resultado, x:Name é menos eficiente do que x:Key porque esse campo precisa ser inicializado quando a página é carregada.

A extensão de marcação StaticResource pode recuperar recursos somente com um nome de cadeia de caracteres (x:Key ou x:Name). No entanto, a estrutura XAML também procura recursos de estilo implícitos (aqueles que usam TargetType em vez de x:Key ou x:Name) quando decide qual modelo de estilo & usar para um controle que não definiu as propriedades Style e ContentTemplate ou ItemTemplate .

Aqui, o Estilo tem uma chave implícita de typeof(Button) , e, como o Button na parte inferior da página não especifica uma propriedade de Estilo , ele procura um estilo com chave de typeof(Button) .

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Red"/>
        </Style>
    </Page.Resources>
    <Grid>
       <!-- This button will have a red background. -->
       <Button Content="Button" Height="100" VerticalAlignment="Center" Width="100"/>
    </Grid>
</Page>

Para saber mais sobre estilos implícitos e como eles funcionam, veja Estilizando controles e Modelos de controle.

Procurar recursos no código

Você acede a membros do dicionário de recursos como qualquer outro dicionário.

Advertência

Quando você executa uma pesquisa de recursos no código, somente os recursos no Page.Resources dicionário são examinados. Ao contrário da extensão de marcação StaticResource , o código não volta para o dicionário Application.Resources se os recursos não forem encontrados no primeiro dicionário.

Este exemplo mostra como recuperar o redButtonStyle recurso do dicionário de recursos de uma página:

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Page.Resources>
        <Style TargetType="Button" x:Key="redButtonStyle">
            <Setter Property="Background" Value="red"/>
        </Style>
    </Page.Resources>
</Page>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            Style redButtonStyle = (Style)this.Resources["redButtonStyle"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        Windows::UI::Xaml::Style style = Resources().TryLookup(winrt::box_value(L"redButtonStyle")).as<Windows::UI::Xaml::Style>();
    }

Para procurar recursos de todo o aplicativo a partir do código, use Application.Current.Resources para obter o dicionário de recursos do aplicativo, conforme mostrado aqui.

<Application
    x:Class="MSDNSample.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SpiderMSDN">
    <Application.Resources>
        <Style TargetType="Button" x:Key="appButtonStyle">
            <Setter Property="Background" Value="red"/>
        </Style>
    </Application.Resources>

</Application>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            Style appButtonStyle = (Style)Application.Current.Resources["appButtonStyle"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        Windows::UI::Xaml::Style style = Application::Current().Resources()
                                                               .TryLookup(winrt::box_value(L"appButtonStyle"))
                                                               .as<Windows::UI::Xaml::Style>();
    }

Você também pode adicionar um recurso de aplicativo no código.

Há duas coisas a ter em mente ao fazer isso.

  • Primeiro, você precisa adicionar os recursos antes que qualquer página tente usar o recurso.
  • Em segundo lugar, você não pode adicionar recursos no construtor do aplicativo.

Você pode evitar ambos os problemas se adicionar o recurso no método Application.OnLaunched , como este.

// App.xaml.cs
    
sealed partial class App : Application
{
    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        if (rootFrame == null)
        {
            SolidColorBrush brush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 0, 255, 0)); // green
            this.Resources["brush"] = brush;
            // … Other code that VS generates for you …
        }
    }
}
// App.cpp

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == nullptr)
    {
        Windows::UI::Xaml::Media::SolidColorBrush brush{ Windows::UI::ColorHelper::FromArgb(255, 0, 255, 0) };
        Resources().Insert(winrt::box_value(L"brush"), winrt::box_value(brush));
        // … Other code that VS generates for you …

Cada FrameworkElement pode ter um ResourceDictionary

FrameworkElement é uma classe base da qual os controles herdam e tem uma propriedade Resources. Portanto, você pode adicionar um dicionário de recursos local a qualquer FrameworkElement.

Aqui, tanto a Página como a Fronteira têm dicionários de recursos, e ambos têm um recurso chamado "saudação". O TextBlock chamado 'textBlock2' está dentro do Border, portanto, a sua pesquisa de recursos examina primeiro os recursos do Border, depois os recursos da Pagee, em seguida, os recursos do Application. O TextBlock lerá "Hola mundo".

Para acessar os recursos desse elemento a partir do código, use a propriedade Resources desse elemento. Ao aceder aos recursos de um FrameworkElementno código, em vez de em XAML, a pesquisa será feita apenas nesse dicionário, não nos dicionários do elemento pai.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <x:String x:Key="greeting">Hello world</x:String>
    </Page.Resources>
    
    <StackPanel>
        <!-- Displays "Hello world" -->
        <TextBlock x:Name="textBlock1" Text="{StaticResource greeting}"/>

        <Border x:Name="border">
            <Border.Resources>
                <x:String x:Key="greeting">Hola mundo</x:String>
            </Border.Resources>
            <!-- Displays "Hola mundo" -->
            <TextBlock x:Name="textBlock2" Text="{StaticResource greeting}"/>
        </Border>

        <!-- Displays "Hola mundo", set in code. -->
        <TextBlock x:Name="textBlock3"/>
    </StackPanel>
</Page>

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            textBlock3.Text = (string)border.Resources["greeting"];
        }
    }
    MainPage::MainPage()
    {
        InitializeComponent();
        textBlock3().Text(unbox_value<hstring>(border().Resources().TryLookup(winrt::box_value(L"greeting"))));
    }

Dicionários de recursos mesclados

Um dicionário de recursos mesclado combina um dicionário de recursos em outro, normalmente em um ficheiro diferente.

Dica Você pode criar um arquivo de dicionário de recursos no Microsoft Visual Studio usando a opção Adicionar Novo Item... opção Dicionário de Recursos no menu Project.

Aqui, você define um dicionário de recursos em um arquivo XAML separado chamado Dictionary1.xaml.

<!-- Dictionary1.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

Para usar esse dicionário, mescle-o com o dicionário da sua página:

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>

            <x:String x:Key="greeting">Hello world</x:String>

        </ResourceDictionary>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource brush}" Text="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

Veja o que acontece neste exemplo. Em <Page.Resources>, você declara <ResourceDictionary>. A estrutura XAML cria implicitamente um dicionário de recursos para você quando você adiciona recursos ao <Page.Resources>, no entanto, neste caso, você não quer apenas um dicionário de recursos, você quer um que contenha dicionários mesclados.

Então você declara <ResourceDictionary>e, em seguida, adiciona coisas à sua coleção <ResourceDictionary.MergedDictionaries>. Cada uma dessas entradas assume a forma <ResourceDictionary Source="Dictionary1.xaml"/>. Para adicionar mais de um dicionário, basta adicionar uma <ResourceDictionary Source="Dictionary2.xaml"/> entrada após a primeira entrada.

Depois de <ResourceDictionary.MergedDictionaries>…</ResourceDictionary.MergedDictionaries>, você pode, opcionalmente, colocar recursos adicionais no seu dicionário principal. Você usa recursos de um dicionário mesclado como se fosse um dicionário normal. No exemplo acima, {StaticResource brush} localiza o recurso no dicionário filho/mesclado (Dictionary1.xaml), enquanto {StaticResource greeting} localiza seu recurso no dicionário da página principal.

Na sequência de pesquisa de recursos, um dicionário MergedDictionaries é verificado somente após uma verificação de todos os outros recursos chaveados desse ResourceDictionary. Depois de pesquisar aquele nível, a pesquisa atinge os dicionários mesclados e cada item no MergedDictionaries é verificado. Se existirem vários dicionários mesclados, esses dicionários serão verificados no inverso da ordem em que são declarados na propriedade MergedDictionaries . No exemplo a seguir, se Dictionary2.xaml e Dictionary1.xaml declararam a mesma chave, a chave de Dictionary2.xaml será usada primeiro porque é a última no conjunto MergedDictionaries .

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
                <ResourceDictionary Source="Dictionary2.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>

    <TextBlock Foreground="{StaticResource brush}" Text="greetings!" VerticalAlignment="Center"/>
</Page>

Dentro do escopo de qualquer ResourceDictionary, o dicionário é verificado para garantir que as chaves sejam únicas. No entanto, esse escopo não se estende a diferentes itens em diferentes arquivos MergedDictionaries.

Você pode usar a combinação da sequência de pesquisa e a falta de imposição de chave exclusiva entre escopos de dicionário mesclado para criar uma sequência de valores de fallback de ResourceDictionary recursos. Por exemplo, você pode armazenar as preferências do usuário para uma determinada cor de pincel no último dicionário de recursos mesclado na sequência, usando um dicionário de recursos que sincroniza com os dados de estado e preferência do usuário do seu aplicativo. No entanto, se ainda não existirem preferências de utilizador, pode definir essa mesma chave para um recurso ResourceDictionary no arquivo inicial MergedDictionaries, e ela pode servir como o valor padrão. Lembre-se de que qualquer valor fornecido num dicionário de recursos principal é sempre verificado antes dos dicionários mesclados, portanto, se quiser usar a técnica de retorno, não defina esse recurso num dicionário de recursos principal.

Recursos temáticos e dicionários temáticos

Um ThemeResource é semelhante a um StaticResource, mas a pesquisa dos recursos é reavaliada quando o tema é alterado.

Neste exemplo, define-se o primeiro plano de um TextBlock como um valor do tema atual.

<TextBlock Text="hello world" Foreground="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" VerticalAlignment="Center"/>

Um dicionário de temas é um tipo especial de dicionário mesclado que contém os recursos que variam com o tema que um usuário está usando atualmente em seu dispositivo. Por exemplo, o tema "claro" pode usar um pincel de cor branca, enquanto o tema "escuro" pode usar um pincel de cor escura. O pincel altera o recurso para o qual ele resolve, mas, caso contrário, a composição de um controle que usa o pincel como um recurso pode ser a mesma. Para reproduzir o comportamento de alternância de tema nos seus modelos e estilos próprios, em vez de usar a propriedade MergedDictionaries para mesclar itens nos dicionários principais, use a propriedade ThemeDictionaries.

Cada elemento ResourceDictionary dentro de ThemeDictionaries deve ter um valor de x:Key. O valor é uma cadeia de caracteres que nomeia o tema relevante — por exemplo, "Default", "Dark", "Light" ou "HighContrast". Normalmente, Dictionary1 e Dictionary2 definem recursos que têm os mesmos nomes, mas valores diferentes.

Aqui, você usa texto vermelho para o tema claro e texto azul para o tema escuro.

<!-- Dictionary1.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

<!-- Dictionary2.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MSDNSample">

    <SolidColorBrush x:Key="brush" Color="blue"/>

</ResourceDictionary>

Neste exemplo, define-se o primeiro plano de um TextBlock como um valor do tema atual.

<Page
    x:Class="MSDNSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" x:Key="Light"/>
                <ResourceDictionary Source="Dictionary2.xaml" x:Key="Dark"/>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <TextBlock Foreground="{StaticResource brush}" Text="hello world" VerticalAlignment="Center"/>
</Page>

Para dicionários de temas, o dicionário ativo para a pesquisa de recursos muda dinamicamente, sempre que a extensão de marcação ThemeResource é utilizada para a referência e o sistema deteta uma alteração de tema. O comportamento de pesquisa que é feito pelo sistema é baseado no mapeamento do tema ativo para o x:Key de um dicionário de tema específico.

Pode ser útil examinar a maneira como os dicionários de tema são estruturados nos recursos de design XAML padrão, que são paralelos aos modelos que o Tempo de Execução do Windows usa por padrão para seus controles. Abra os arquivos XAML em \(Arquivos de Programas)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic usando um editor de texto ou seu IDE. Observe como os dicionários de tema são definidos primeiro em generic.xaml e como cada dicionário de tema define as mesmas chaves. Cada uma dessas chaves é então referenciada por elementos de composição nos vários elementos chaveados que estão fora dos dicionários de tema e definidos posteriormente no XAML. Há também um arquivo themeresources.xaml separado para design que contém apenas os recursos do tema e modelos extras, não os modelos de controle padrão. As áreas de tema são duplicatas do que você veria em generic.xaml.

Quando você usa ferramentas de design XAML para editar cópias de estilos e modelos, as ferramentas de design extraem seções dos dicionários de recursos de design XAML e as colocam como cópias locais de elementos de dicionário XAML que fazem parte do seu aplicativo e projeto.

Para obter mais informações e obter uma lista dos recursos específicos do tema e do sistema disponíveis para seu aplicativo, consulte Recursos de tema XAML.

Comportamento de pesquisa para referências de recursos XAML

Comportamento de pesquisa é o termo que descreve como o sistema de recursos XAML tenta localizar um recurso XAML. A pesquisa ocorre quando uma chave é referenciada como uma referência de recurso XAML de algum lugar no XAML do aplicativo. Primeiro, o sistema de recursos tem um comportamento previsível para onde verificará a existência de um recurso com base no escopo. Se um recurso não for encontrado no escopo inicial, o escopo será expandido. O comportamento de procura continua por todos os locais e escopos onde um recurso XAML possa ser definido por uma aplicação ou pelo sistema. Se todas as possíveis tentativas de pesquisa de recursos falharem, geralmente ocorre um erro. Normalmente, é possível eliminar esses erros durante o processo de desenvolvimento.

O comportamento de pesquisa para referências de recursos XAML começa com o objeto onde o uso real é aplicado e sua própria propriedade Resources. Se um ResourceDictionary existir lá, esse ResourceDictionary será verificado, procurando por um item com a chave solicitada. Esse primeiro nível de pesquisa raramente é relevante porque você geralmente não define e, em seguida, faz referência a um recurso no mesmo objeto. Na verdade, uma propriedade Recursos muitas vezes não existe aqui. Você pode fazer referências de recursos XAML de praticamente qualquer lugar em XAML; você não está limitado às propriedades de subclasses FrameworkElement.

Em seguida, a sequência de procura verifica o próximo objeto pai na árvore de objetos de execução do aplicativo. Se existir um FrameworkElement.Resources que contenha um ResourceDictionary, o item do dicionário com a chave especificada será solicitado. Se o recurso for encontrado, a sequência de pesquisa será interrompida e o objeto será fornecido ao local onde a referência foi feita. Caso contrário, o comportamento de pesquisa progride para o próximo nível superior em direção à raiz da árvore de objetos. A pesquisa continua recursivamente para cima até que o elemento raiz do XAML seja alcançado, esgotando a pesquisa de todos os possíveis locais de recursos imediatos.

Observação

É uma prática comum definir todos os recursos imediatos no nível raiz de uma página, tanto para aproveitar esse comportamento de pesquisa de recursos quanto como uma convenção do estilo de marcação XAML.

Se o recurso solicitado não for encontrado nos recursos imediatos, a próxima etapa de pesquisa é verificar a propriedade Application.Resources . Application.Resources é o melhor lugar para colocar quaisquer recursos específicos do aplicativo que são referenciados por várias páginas na estrutura de navegação do seu aplicativo.

Importante

A ordem dos recursos adicionados a um ResourceDictionary afeta a ordem em que eles são aplicados. O XamlControlsResources dicionário substitui muitas chaves de recurso padrão e, portanto, deve ser adicionado a Application.Resources primeiro, para que não substitua nenhum outro estilo ou recurso personalizado na sua aplicação.

Os modelos de controle têm outro local possível na pesquisa de referência: dicionários de temas. Um dicionário de tema é um único arquivo XAML que tem um elemento ResourceDictionary como raiz. O dicionário de temas pode ser um dicionário combinado de Application.Resources. O dicionário de temas também pode ser o dicionário de temas específico para o controle personalizado baseado num modelo.

Finalmente, há uma consulta aos recursos da plataforma. Os recursos da plataforma incluem os modelos de controle definidos para cada um dos temas da interface do usuário do sistema e que definem a aparência padrão de todos os controles que você usa para a interface do usuário em um aplicativo do Tempo de Execução do Windows. Os recursos da plataforma também incluem um conjunto de recursos nomeados relacionados à aparência e aos temas de todo o sistema. Esses recursos são tecnicamente um item de MergedDictionaries e, portanto, estão disponíveis para pesquisa a partir de XAML ou código depois de o aplicativo ser carregado. Por exemplo, os recursos do tema do sistema incluem um recurso chamado "SystemColorWindowTextColor" que fornece uma definição de cor para corresponder à cor do texto do aplicativo à cor do texto de uma janela do sistema determinada pelo sistema operacional e preferências do usuário. Outros estilos XAML para a sua aplicação podem referir-se a este estilo, ou o seu código pode obter um valor de recurso consultado (e convertê-lo para a cor no caso de exemplo).

Para obter mais informações e obter uma lista dos recursos específicos do tema e do sistema disponíveis para um aplicativo do Windows que usa XAML, consulte Recursos de tema XAML.

Se a chave solicitada ainda não for encontrada em nenhum desses locais, ocorrerá um erro/exceção de análise XAML. Em determinadas circunstâncias, a exceção de análise XAML pode ser uma exceção em tempo de execução que não é detetada por uma ação de compilação de marcação XAML ou por um ambiente de design XAML.

Devido ao comportamento de pesquisa hierárquica para dicionários de recursos, você pode definir deliberadamente vários itens de recurso que cada um tem o mesmo valor de cadeia de caracteres que a chave, desde que cada recurso seja definido em um nível diferente. Em outras palavras, embora as chaves devam ser exclusivas dentro de qualquer ResourceDictionary , o requisito de exclusividade não se estende à sequência de comportamento de pesquisa como um todo. Durante a pesquisa, somente o primeiro objeto recuperado com êxito é usado para a referência de recurso XAML e, em seguida, a pesquisa é interrompida. Você pode usar esse comportamento para solicitar o mesmo recurso XAML por chave em várias posições dentro do XAML do seu aplicativo, mas obter recursos diferentes de volta, dependendo do escopo a partir do qual a referência de recurso XAML foi feita e como essa pesquisa específica se comporta.

Referências antecipadas num ResourceDictionary

As referências de recursos XAML em um dicionário de recursos específico devem fazer referência a um recurso que já foi definido com uma chave, e esse recurso deve aparecer lexicamente antes da referência de recurso. As referências de encaminhamento não podem ser resolvidas por uma referência de recurso XAML. Por esse motivo, se você usar referências de recursos XAML de dentro de outro recurso, deverá projetar sua estrutura de dicionário de recursos para que os recursos usados por outros recursos sejam definidos primeiro em um dicionário de recursos.

Os recursos definidos no nível do aplicativo não podem fazer referências a recursos imediatos. Isso equivale a tentar uma referência antecipada, porque os recursos da aplicação são efetivamente processados primeiro (quando a aplicação é iniciada pela primeira vez e antes que qualquer conteúdo da página de navegação seja carregado). No entanto, qualquer recurso imediato pode fazer uma referência a um recurso de aplicação, e isso pode ser uma técnica útil para evitar situações de referência antecipada.

Os recursos XAML devem ser compartilháveis

Para que um objeto exista em um ResourceDictionary, esse objeto deve ser compartilhável.

Ser compartilhável é necessário porque, quando a árvore de objetos de um aplicativo é construída e usada em tempo de execução, os objetos não podem existir em vários locais na árvore. Internamente, o sistema de recursos cria cópias de valores de recursos para usar no gráfico de objetos do seu aplicativo quando cada recurso XAML é solicitado.

Um ResourceDictionary e o XAML da Execução do Windows geralmente suporta esses objetos para usabilidade compartilhável.

Você também pode usar tipos personalizados como um recurso compartilhável se seguir os padrões de implementação necessários. Você define essas classes em seu código de suporte (ou em componentes de tempo de execução que você inclui) e, em seguida, instancia essas classes em XAML como um recurso. Exemplos são fontes de dados de objetos e implementações IValueConverter para ligação de dados.

Os tipos personalizados devem ter um construtor padrão, porque é isso que um analisador XAML usa para instanciar uma classe. Os tipos personalizados usados como recursos não podem ter a classe UIElement na sua herança, porque um UIElement nunca pode ser compartilhável (destina-se sempre a representar exatamente um elemento de interface do usuário que existe numa posição única no grafo de objetos da aplicação em tempo de execução).

Escopo de uso do UserControl

Um elemento UserControl tem uma situação especial para o comportamento de pesquisa de recursos porque possui os conceitos inerentes de um escopo de definição e um escopo de uso. Um UserControl que faz referência a um recurso XAML a partir do seu escopo de definição deve ser capaz de suportar a pesquisa desse recurso dentro da sequência de pesquisa do seu próprio escopo de definição, ou seja, não consegue acessar recursos do aplicativo. A partir do escopo de uso de um UserControl, uma referência de recurso é considerada parte da sequência de pesquisa até à raiz da página de uso (assim como qualquer outra referência de recurso feita a partir de um objeto numa árvore de objetos carregada) e pode aceder aos recursos da aplicação.

ResourceDictionary e XamlReader.Load

Você pode usar um ResourceDictionary como raiz ou como parte da entrada XAML para o método XamlReader.Load . Você também pode incluir referências de recursos XAML nesse XAML se todas essas referências forem completamente independentes no XAML enviado para carregamento. XamlReader.Load analisa o XAML em um contexto que não está ciente de nenhum outro ResourceDictionary objetos, nem mesmo Application.Resources. Além disso, não use {ThemeResource} de dentro do XAML enviado para XamlReader.Load.

Usando um ResourceDictionary a partir do código

A maioria dos cenários para um ResourceDictionary é tratada exclusivamente em XAML. Você declara o contêiner ResourceDictionary e os recursos dentro como um arquivo XAML ou um conjunto de nós XAML em um arquivo de definição de interface do usuário. E, em seguida, você usa referências de recursos XAML para solicitar esses recursos de outras partes do XAML. Ainda assim, há certos cenários em que seu aplicativo pode querer ajustar o conteúdo de um ResourceDictionary usando o código que é executado enquanto o aplicativo está em execução ou, pelo menos, consultar o conteúdo de um ResourceDictionary para ver se um recurso já está definido. Essas chamadas de código são feitas numa instância ResourceDictionary, portanto, deve primeiro recuperar uma — seja uma ResourceDictionary imediata em algum lugar na árvore de objetos ao obter FrameworkElement.Resources, ou Application.Current.Resources.

No código C# ou Microsoft Visual Basic, você pode fazer referência a um recurso em um determinado ResourceDictionary usando o indexador (Item). Um ResourceDictionary é um dicionário com chave de cadeia de caracteres, portanto, o indexador usa a chave de cadeia de caracteres em vez de um índice inteiro. No código de extensões de componente do Visual C++ (C++/CX), use Lookup.

Ao usar código para examinar ou alterar um ResourceDictionary, o comportamento de APIs como Consulta ou Item não passa de recursos imediatos para recursos do aplicativo; esse é um comportamento do analisador XAML que ocorre apenas quando as páginas XAML são carregadas. Em tempo de execução, o escopo das chaves é autônomo para a instância ResourceDictionary que você está usando no momento. No entanto, esse âmbito estende-se a MergedDictionaries.

Além disso, se você solicitar uma chave que não existe no ResourceDictionary, pode não haver um erro; O valor de retorno pode simplesmente ser fornecido como nulo. No entanto, ainda poderá obter um erro se tentar usar o nulo retornado como um valor. O erro viria do setter da propriedade, não da chamada ao seu ResourceDictionary. A única maneira de evitar um erro seria se a propriedade aceitasse nulo como um valor válido. Observe como esse comportamento contrasta com o comportamento de pesquisa XAML no tempo de análise XAML; uma falha ao resolver a chave fornecida do XAML em tempo de análise resulta em um erro de análise XAML, mesmo nos casos em que a propriedade poderia ter aceitado nulo.

Os dicionários de recursos mesclados são incluídos no escopo de índice do dicionário de recursos primário que faz referência ao dicionário mesclado em tempo de execução. Em outras palavras, pode-se usar o Item ou a Pesquisa do dicionário primário para encontrar quaisquer objetos que foram realmente definidos no dicionário mesclado. Nesse caso, o comportamento de pesquisa é semelhante ao comportamento de pesquisa XAML em tempo de análise: se houver vários objetos em dicionários mesclados que tenham a mesma chave, o objeto do último dicionário adicionado será retornado.

Você tem permissão para adicionar itens a um ResourceDictionary de existente chamando Adicionar (C# ou Visual Basic) ou Inserir (C++/CX). Você pode adicionar os itens a recursos imediatos ou recursos do aplicativo. Qualquer uma dessas chamadas de API requer uma chave, que satisfaz o requisito de que cada item num ResourceDictionary deve ter uma chave. No entanto, os itens que forem adicionados a um ResourceDictionary em tempo de execução não são relevantes para as referências de recursos XAML. A pesquisa necessária para referências de recursos XAML acontece quando esse XAML é analisado pela primeira vez à medida que o aplicativo é carregado (ou uma alteração de tema é detetada). Os recursos adicionados às coleções em tempo de execução não estavam disponíveis na época, e alterar o ResourceDictionary do não invalida um recurso já recuperado dele, mesmo que você altere o valor desse recurso.

Você também pode remover itens de um ResourceDictionary em tempo de execução, fazer cópias de alguns ou todos os itens ou outras operações. A listagem de membros para ResourceDictionary indica quais APIs estão disponíveis. Observe que, como o ResourceDictionary tem uma API projetada para suportar suas interfaces de coleta subjacentes, suas opções de API diferem dependendo se você está usando C# ou Visual Basic versus C++/CX.

Dicionário de Recursos e localização

Um XAML ResourceDictionary pode conter inicialmente cadeias de caracteres que devem ser localizadas. Em caso afirmativo, armazene essas cadeias de caracteres como recursos do projeto em vez de em um ResourceDictionary. Retire as cadeias de caracteres do XAML e, em vez disso, atribua ao elemento proprietário um valor de diretiva x:Uid . Em seguida, defina um recurso em um arquivo de recursos. Indique um nome de recurso no formato XUIDValue.PropertyName e forneça um valor de recurso da string que deve ser localizada.

Pesquisa personalizada de recursos

Para cenários avançados, você pode implementar uma classe que pode ter um comportamento diferente do comportamento de pesquisa de referência de recurso XAML descrito neste tópico. Para fazer isso, implemente a classe CustomXamlResourceLoadere, em seguida, é possível aceder a esse comportamento utilizando a CustomResource extensão de marcação para referências de recursos em vez de usar StaticResource ou ThemeResource. A maioria dos aplicativos não terá cenários que exijam isso. Para obter mais informações, consulte CustomXamlResourceLoader.