Compartilhar via


Referências de recursos de ResourceDictionary e XAML

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

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

Pré-requisitos

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

Definir e usar recursos XAML

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

<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".
  • - Pesquisa o recurso com a chave "saudação", que é atribuída à propriedade do Text do TextBlock.

Observação

Não confunda os conceitos relacionados ao ResourceDictionary com a ação de build Resource, arquivos de recurso (.resw) ou outros "recursos" que são discutidos no contexto de estruturar o projeto de código que produz o seu pacote de aplicativos.

Os recursos não precisam ser cadeias de caracteres; eles podem ser qualquer objeto compartilhável, como estilos, modelos, pincéis e cores. No entanto, controles, formas e outros FrameworkElementnão são compartilháveis, portanto, não podem ser declarados como recursos reutilizáveis. Para obter mais informações sobre compartilhamento, consulte a seção Recursos XAML devem ser compartilháveis, posteriormente 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, há algumas outras maneiras de especificar uma chave:

  • Estilo e ControlTemplate exigem um TargetType, e 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. (Veja exemplos abaixo)
  • recursos de DataTemplate que têm 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 código atrás do campo para o recurso. Como resultado, x:Name é menos eficiente que x:Key porque esse campo precisa ser inicializado quando a página é carregada.

A extensão de marcação StaticResource pode recuperar recursos apenas com um nome de cadeia de caracteres (x:Key ou x:Name). No entanto, a estrutura XAML também procura recursos de estilo implícito (aqueles que usam TargetType em vez de x:Key ou x:Name) quando decide qual estilo &modelo 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 Botão 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 obter mais informações sobre estilos implícitos e como eles funcionam, consulte controles de estilo e modelos de controle.

Pesquisar recursos no código

Você acessa membros do dicionário de recursos como faz com qualquer outro dicionário.

Aviso

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 retornará ao Application.Resources dicionário 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 pesquisar recursos em 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 para 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ê poderá evitar ambos os problemas se adicionar o recurso ao método Application.OnLaunched , assim.

// 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 ela possui a propriedade Resources. Portanto, você pode adicionar um dicionário de recursos local a qualquer FrameworkElement.

Aqui, a Página e a Borda têm dicionários de recursos e ambos têm um recurso chamado "saudação". O TextBlock denominado 'textBlock2' está dentro do Border, portanto, sua pesquisa de recursos procura primeiro nos recursos do Border, depois nos recursos do Pagee, em seguida, nos 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. Acessar um FrameworkElementrecursos no código, em vez de XAML, será exibido 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, geralmente em outro arquivo.

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

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, mescla-o com o dicionário da 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 a <Page.Resources>; no entanto, neste caso, você não quer apenas qualquer dicionário de recursos, você quer um que contenha dicionários mesclados.

Portanto, você declara <ResourceDictionary>e depois adiciona itens à 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 <ResourceDictionary.MergedDictionaries>…</ResourceDictionary.MergedDictionaries>, opcionalmente, você pode colocar recursos adicionais em seu dicionário principal. Você usa recursos de um dicionário mesclado como um dicionário regular. No exemplo acima, {StaticResource brush} localiza o recurso no dicionário filho/mesclado (Dictionary1.xaml), enquanto {StaticResource greeting} localiza seu recurso no dicionário de páginas principal.

Na sequência de pesquisa de recursos, um dicionário MergedDictionaries é chequeado somente após a checagem de todos os outros recursos com chave desse ResourceDictionary. Depois de consultar esse nível, a pesquisa atinge os dicionários mesclados e cada item em 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 declararem 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 quanto à exclusividade da chave. No entanto, esse escopo não se estende entre itens diferentes em diferentes arquivos de MergedDictionaries .

Você pode usar a combinação da sequência de pesquisa e a falta de imposição de chave exclusiva em escopos de dicionário mesclados para criar uma sequência de valores de substituição de recursos ResourceDictionary. Por exemplo, você pode armazenar as preferências do usuário para uma cor de pincel específica no último dicionário de recursos mesclado na sequência, usando um dicionário de recursos que sincroniza com os dados de preferência do usuário e de estado do aplicativo. Caso ainda não existam preferências de usuário, você pode definir essa mesma cadeia de caracteres de chave para um recurso no ResourceDictionary do arquivo inicial de MergedDictionaries, e ele pode servir como o valor de fallback. Lembre-se de que qualquer valor fornecido em um dicionário de recursos primário é sempre verificado antes que os dicionários mesclados sejam verificados, portanto, se você quiser usar a técnica de fallback, não defina esse recurso em um dicionário de recursos primário.

Recursos de tema e dicionários de temas

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

Neste exemplo, você define o primeiro plano de um TextBlock para 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 em seus próprios modelos e estilos, em vez de usar MergedDictionaries como a propriedade para mesclar itens nos dicionários principais, use a propriedade ThemeDictionaries.

Cada elemento ResourceDictionary em ThemeDictionaries deve ter um valor x:Key. O valor é uma cadeia de caracteres que nomeia o tema relevante, por exemplo, "Padrão", "Escuro", "Claro" ou "HighContrast". Normalmente, Dictionary1 e Dictionary2 definirão 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, você define o primeiro plano de um TextBlock para 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 a ser usado para pesquisa de recursos muda dinamicamente toda vez que a extensão de marcação ThemeResource é utilizada para fazer a referência, e o sistema detecta uma alteração de tema. O comportamento de pesquisa realizado pelo sistema baseia-se no mapeamento do tema ativo para a chave x:Key de um dicionário de temas específico.

Pode ser útil examinar a forma como os dicionários de temas são estruturados nos recursos de design XAML padrão, que são paralelos aos modelos que o Windows Runtime usa por padrão para seus controles. Abra os arquivos XAML em \(Arquivos de Programas)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<versão do SDK>\Generic usando um editor de texto ou seu IDE. Observe como os dicionários de temas são definidos primeiro em generic.xaml e como cada dicionário de temas define as mesmas chaves. Cada chave desse tipo é então referenciada por elementos de composição nos vários elementos chave que estão fora dos dicionários de temas e definidos posteriormente no XAML. Há também um arquivo themeresources.xaml separado para design que contém apenas os recursos de 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 para obter uma lista dos recursos específicos do tema e do sistema que estão disponíveis para seu aplicativo, consulte os recursos de tema XAML.

Comportamento de procura para referências de recurso XAML

Comportamento de busca é o termo que descreve como o sistema XAML de recursos tenta encontrar 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 pesquisa continua em todos os locais e escopos em que um recurso XAML poderia possivelmente ser definido por um aplicativo ou pelo sistema. Se todas as possíveis tentativas de pesquisa de recursos falharem, um erro geralmente resultará. Geralmente, é possível eliminar esses erros durante o processo de desenvolvimento.

O comportamento de busca para referências de recurso XAML começa com o objeto onde o uso efetivo é aplicado e sua própria propriedade Resources. Se houver um ResourceDictionary, aquele ResourceDictionary será verificado para um item que tenha a chave solicitada. Esse primeiro nível de pesquisa raramente é relevante porque você geralmente não define e faz referência a um recurso no mesmo objeto. Na verdade, uma propriedade Resources geralmente não existe aqui. Você pode fazer referências de recurso XAML de praticamente qualquer lugar no XAML; você não está limitado às propriedades das subclasses FrameworkElement .

A sequência de pesquisa verifica o próximo objeto pai na árvore de objetos de runtime do aplicativo. Se um FrameworkElement.Resources existir e contiver um ResourceDictionary, o item do dicionário com a chave de string especificada é solicitado. Se o recurso for encontrado, a sequência de pesquisa será interrompida e o objeto será fornecido para o local onde a referência foi feita. Caso contrário, o comportamento de pesquisa passa para o próximo nível pai em direção à raiz da árvore de objetos. A pesquisa continua recursivamente para cima até que o elemento raiz do XAML seja atingido, 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 também 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 será verificar a propriedade Application.Resources . Application.Resources é o melhor lugar para colocar todos os recursos específicos do aplicativo referenciados por várias páginas na estrutura de navegação do aplicativo.

Importante

A ordem dos recursos adicionados a um ResourceDictionary afeta a ordem na qual eles são aplicados. O XamlControlsResources dicionário substitui muitas chaves de recurso padrão e, portanto, deve ser adicionado primeiro a Application.Resources para que não substitua outros estilos ou recursos personalizados em seu aplicativo.

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

Por fim, há uma busca por recursos na 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 interface do usuário em um aplicativo do Windows Runtime. Os recursos da plataforma também incluem um conjunto de recursos nomeados relacionados à aparência e temas do sistema inteiro. Esses recursos são tecnicamente um item MergedDictionaries e, portanto, estão disponíveis para acesso a partir de XAML ou código depois que o aplicativo está carregado. Por exemplo, os recursos de tema do sistema incluem um recurso chamado "SystemColorWindowTextColor" que fornece uma definição de Cor para corresponder a cor do texto do aplicativo à cor de texto de uma janela do sistema proveniente do sistema operacional e das preferências do usuário. Outros estilos XAML para seu aplicativo podem se referir a esse estilo ou seu código pode obter um valor de pesquisa de recurso (e convertê-lo em Cor no caso de exemplo).

Para obter mais informações e para obter uma lista dos recursos específicos do tema e do sistema que estão disponíveis para um aplicativo do Windows que usa XAML, consulte os 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 de tempo de execução que não é detectada por uma ação de compilação de marcação XAML ou por uma ferramenta de design XAML.

Devido ao comportamento de pesquisa em camadas 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 precisem ser exclusivas em 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 desse tipo recuperado com êxito é usado para a referência de recurso XAML e, em seguida, a pesquisa é interrompida. Você pode usar este comportamento para solicitar o mesmo recurso XAML por chave em várias posições dentro do XAML do seu aplicativo, mas receber recursos diferentes, dependendo do escopo de onde a referência ao recurso XAML foi realizada e de como essa pesquisa específica se comporta.

Referências antecipadas em um ResourceDictionary

As referências de recurso 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. Referências avançadas não podem ser resolvidas por uma referência de recurso XAML. Por esse motivo, se você usar referências de recurso XAML de dentro de outro recurso, deverá criar 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, pois os recursos do aplicativo são processados inicialmente (quando o aplicativo é iniciado pela primeira vez e antes de qualquer conteúdo de página de navegação ser carregado). No entanto, qualquer recurso disponível imediatamente pode fazer uma referência a um recurso de aplicativo, 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 recurso a serem usadas no grafo de objeto do aplicativo quando cada recurso XAML é solicitado.

Um ResourceDictionary e o XAML do Windows Runtime de modo geral dão suporte a esses objetos para uso compartilhado.

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 backup (ou em componentes de runtime que você inclui) e, em seguida, instancia essas classes em XAML como um recurso. Exemplos são fontes de dados de objeto e implementações IValueConverter para associação de dados.

Os tipos personalizados devem ter um construtor padrão, pois é isso que um analisador XAML usa para instanciar uma classe. Tipos personalizados usados como recursos não podem ter a classe UIElement em sua herança, pois um UIElement nunca pode ser compartilhável (ele sempre se destina a representar exatamente um elemento de interface do usuário que existe em uma posição no grafo de objeto do seu aplicativo de runtime).

Escopo de UserControl

Um elemento UserControl tem uma situação especial para o comportamento de pesquisa de recursos porque tem os conceitos inerentes de um escopo de definição e um escopo de uso. Um UserControl que faz uma referência a um recurso XAML de seu escopo de definição deve conseguir buscar esse recurso dentro de seu próprio escopo de definição—ou seja, não pode acessar recursos do aplicativo. Na perspectiva de uso de um UserControl, uma referência de recurso é tratada como estando dentro da sequência de pesquisa em direção à raiz da página de utilização (assim como qualquer outra referência de recurso feita a partir de um objeto em uma árvore de objetos já carregada) e pode acessar recursos do aplicativo.

ResourceDictionary e XamlReader.Load

Você pode usar um ResourceDictionary como raiz ou parte integrante da entrada XAML para o método XamlReader.Load. Você também pode incluir referências a recursos XAML nesse XAML, desde que todas essas referências sejam totalmente autossuficientes no XAML enviado para carregamento. XamlReader.Load analisa o XAML em um contexto que não está ciente de nenhum outro objeto ResourceDictionary, nem mesmo de 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 ResourceDictionary como um contêiner e os recursos que nele estão como um arquivo XAML ou um conjunto de nós XAML em um arquivo de definição da interface do usuário. Em seguida, você usa referências de recurso 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 para consultar o conteúdo de um ResourceDictionary para ver se um recurso já está definido. Essas chamadas de código são feitas em uma instância de ResourceDictionary, portanto, você deve primeiro recuperar uma — seja uma ResourceDictionary imediata em algum lugar na árvore de objetos, obtendo FrameworkElement.Resources, ou Application.Current.Resources.

No código C# ou no Microsoft Visual Basic, você pode referenciar 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 o código para examinar ou alterar umResourceDictionary, o comportamento de APIs como busca ou Item não passa de recursos locais para recursos da aplicação; esse é um comportamento do analisador XAML que só acontece quando páginas XAML são carregadas. Em tempo de execução, o escopo das chaves é autocontido na instância de ResourceDictionary que você está usando no momento. No entanto, esse escopo se estende até MergedDictionaries.

Além disso, se você solicitar uma chave que não existe no ResourceDictionary, talvez não haja um erro; o valor retornado pode simplesmente ser fornecido como nulo. No entanto, você ainda poderá receber um erro se tentar usar o valor nulo retornado como um valor. O erro seria proveniente do setter da propriedade, não da sua chamada ResourceDictionary. A única maneira de evitar um erro é 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 a partir do XAML no tempo de análise resulta em um erro de análise XAML, mesmo em casos onde a propriedade poderia ter aceitado nulo.

Dicionários de recursos mesclados são incluídos no escopo do índice do dicionário de recursos primário que faz referência ao dicionário mesclado em tempo de execução. Em outras palavras, você pode usar Item ou Pesquisa do dicionário primário para localizar todos os objetos que de fato foram definidos no dicionário mesclado. Nesse caso, o comportamento de pesquisa se assemelha ao comportamento de pesquisa XAML em tempo de análise: se houver vários objetos em dicionários mesclados que cada um tem a mesma chave, o objeto do dicionário adicionado pela última vez será retornado.

Você tem permissão para adicionar itens a um ResourceDictionary existente chamando Add (C# ou Visual Basic) ou Insert (C++/CX). Você pode adicionar os itens a recursos imediatos ou recursos de aplicativo. Qualquer uma dessas chamadas à API requer uma chave, o que atende ao requisito de que cada item em um ResourceDictionary deve ter uma chave. No entanto, os itens que você adiciona a um ResourceDictionary em tempo de execução não são relevantes para referências de recurso XAML. A pesquisa necessária para referências de recurso XAML ocorre quando esse XAML é analisado pela primeira vez à medida que o aplicativo é carregado (ou uma alteração de tema é detectada). Os recursos adicionados às coleções em tempo de execução não estavam disponíveis, e alterar o ResourceDictionary não invalida um recurso já recuperado dele mesmo se você alterar 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 dar suporte a suas interfaces de coleção subjacentes, suas opções de API diferem dependendo se você estiver usando C# ou Visual Basic versus C++/CX.

ResourceDictionary e localização

Um ResourceDictionary do XAML pode inicialmente conter cadeias de texto que precisam ser traduzidas. Nesse caso, armazene essas cadeias de caracteres como recursos de projeto em vez de em um ResourceDictionary. Tire as strings do XAML e, em vez disso, atribua ao elemento proprietário uma diretiva x:Uid com o valor. Em seguida, defina um recurso em um arquivo de recursos. Forneça um nome de recurso no formulário XUIDValue.PropertyName e um valor de recurso da cadeia de caracteres que deve ser localizado.

Pesquisa de recursos personalizados

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, você implementa a classe CustomXamlResourceLoadere pode então acessar esse comportamento usando a extensão de marcação CustomResource 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.