ResourceDictionary 및 XAML 리소스 참조

XAML을 사용하여 앱에 대한 UI 또는 리소스를 정의할 수 있습니다. 리소스는 일반적으로 두 번 이상 사용할 것으로 예상되는 일부 개체의 정의를 말합니다. 나중에 XAML 리소스를 참조하려면 해당 이름처럼 작동하는 리소스에 대한 키를 지정하십시오. 앱 전체 또는 앱 내의 모든 XAML 페이지에서 리소스를 참조할 수 있습니다. Windows 런타임 XAML에서 ResourceDictionary 요소를 사용하여 리소스를 정의할 수 있습니다. 그런 다음 StaticResource 마크업 확장 또는 ThemeResource 마크업 확장을 사용하여 리소스를 참조할 수 있습니다.

XAML 리소스로 가장 자주 선언하려는 XAML 요소에는 Style, ControlTemplate, 애니메이션 구성 요소 및 Brush 서브클래스가 있습니다. ResourceDictionary 요소 및 키 입력 리소스를 정의하는 방법 및 XAML 리소스가 앱 또는 앱 패키지의 일부로 정의하는 다른 리소스와 어떻게 관련되는지 설명합니다. 또한 MergedDictionariesThemeDictionaries와 같은 리소스 사전 고급 기능에 대해서도 설명합니다.

필수 조건

XAML 태그에 대한 견고한 해석. XAML 개요를 읽어보는 것이 좋습니다.

XAML 리소스 정의 및 사용

XAML 리소스는 태그에서 두 번 이상 참조되는 개체입니다. 리소스는 ResourceDictionary에서 정의되며, 일반적으로 다음과 같이 별도의 파일 또는 마크업 페이지의 맨 위에 정의됩니다.

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

이 예제에서는 다음이 적용됩니다.

  • <Page.Resources>…</Page.Resources> - 리소스 사전을 정의합니다.
  • <x:String> - 'greeting' 키를 사용하여 리소스를 정의합니다.
  • {StaticResource greeting} - TextBlockText 속성에 할당된 'greeting' 키를 사용하여 리소스를 찾습니다.

참고ResourceDictionary 관련 개념을 리소스 빌드 작업, 리소스(.resw) 파일 또는 앱 패키지를 생성하는 코드 프로젝트 구성 컨텍스트에서 설명되는 다른 '리소스'와 혼동하지 마세요.

리소스는 문자열일 필요가 없습니다. 스타일, 템플릿, 브러시 및 색과 같은 공유 가능한 개체일 수 있습니다. 그러나 컨트롤, 모양 및 기타 FrameworkElement는 공유할 수 없으므로 재사용 가능한 리소스라고 선언할 수 없습니다. 공유에 대한 자세한 내용은 이 항목의 뒷부분에서 XAML 리소스를 공유할 수 있어야 하는 섹션을 참조하세요.

여기서 브러시와 문자열은 모두 리소스로 선언되고 페이지의 컨트롤에서 사용됩니다.

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

모든 리소스에는 키가 있어야 합니다. 일반적으로 해당 키는 x:Key="myString"로 정의된 문자열입니다. 키를 지정할 수 있는 몇 가지 다른 방법이 있습니다.

  • StyleControlTemplate에는 TargetType이 필요하며, x:Key가 지정되지 않은 경우 TargetType을 키로 사용합니다. 이 경우 키는 문자열이 아니라 실제 형식 개체이 됩니다. (아래 예제를 참조)
  • x:Key가 지정되지 않은 경우 TargetType이 있는 DataTemplate 리소스는 TargetType을 키로 사용합니다. 이 경우 키는 문자열이 아니라 실제 형식 개체입니다.
  • x:Key 대신 x:Name을 사용할 수 있습니다. 그러나 x:Name에서는 리소스의 코드 숨김 필드도 생성합니다. 따라서 페이지가 로드될 때 해당 필드를 초기화해야 하므로 x:Name은 x:Key보다 효율성이 떨어집니다.

StaticResource 마크업 확장은 문자열 이름(x:Key 또는 x:Name)만 사용하여 리소스를 검색할 수 있습니다. 그러나 StyleContentTemplate 또는 ItemTemplate 속성이 설정되지 않은 컨트롤에 사용할 스타일과 &템플릿을 결정하는 경우 XAML 프레임워크는 암시적 스타일 리소스(x:Key 또는 x:Name이 아니라 TargetType 사용)도 찾습니다.

여기서 Style에는 typeof(Button)의 암시적 키가 있으며 페이지 맨 아래에 있는 Button에서 Style 속성을 지정하지 않으므로 키가 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>

암시적 스타일 및 작동 방식에 대한 자세한 내용은 스타일 지정 컨트롤컨트롤 템플릿을 참조하세요.

코드에서 리소스 조회

다른 사전과 마찬가지로 리소스 사전의 멤버에 액세스합니다.

경고

코드에서 리소스를 찾을 경우 Page.Resources 사전의 리소스만 확인됩니다. StaticResource 마크업 확장과 달리 코드에서는 첫 번째 사전에서 리소스를 찾을 수 없는 경우 Application.Resources 사전으로 대체되지 않습니다.

 

이 예제에서는 페이지 리소스 사전에서 redButtonStyle 리소스를 검색하는 방법을 보여 줍니다.

<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>();
    }

코드에서 앱 전체 리소스를 조회하려면 여기에 표시된 대로 Application.Current.Resources를 사용하여 앱의 리소스 사전을 가져옵니다.

<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>();
    }

코드에서 애플리케이션 리소스를 추가할 수도 있습니다.

이 작업을 수행할 때 유의해야 할 두 가지 사항이 있습니다.

  • 먼저 모든 페이지에서 리소스 사용을 시도하기 전에 리소스를 추가해야 합니다.
  • 둘째, 앱의 생성자에 리소스를 추가할 수 없습니다.

다음과 같이 Application.OnLaunched 메서드에 리소스를 추가하는 경우 두 가지 문제를 모두 방지할 수 있습니다.

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

모든 FrameworkElement에는 ResourceDictionary가 있을 수 있습니다.

FrameworkElement 는 컨트롤이 상속하는 기본 클래스이며 Resources 속성이 있습니다. 따라서 모든 FrameworkElement에 로컬 리소스 사전을 추가할 수 있습니다.

여기서 Page테두리에는 모두 리소스 사전이 있으며 둘 다 'greeting'이라는 리소스가 있습니다. 'textBlock2'라는 TextBlockBorder 내부에 있으므로 해당 리소스를 찾을 때 Border의 리소스를 찾은 후 Page를 찾으십시오. Application 리소스 순으로 검색됩니다. TextBlock은 'Hola mundo'를 읽습니다.

코드에서 요소의 리소스에 액세스하려면 해당 요소의 Resources 속성을 사용합니다. XAML이 아니라 코드에서 FrameworkElement의 리소스에 액세스하면 상위 요소의 사전이 아니라 해당 사전만 검색합니다.

<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"))));
    }

병합된 리소스 사전

병합된 리소스 사전은 일반적으로 다른 파일에서 한 리소스 사전을 다른 리소스 사전으로 결합합니다.

Microsoft Visual Studio에서 프로젝트 메뉴의 추가> 새 항목... > 리소스 사전 옵션을 사용하여 리소스 사전 파일을 만들 수 있습니다.

여기서는 Dictionary1.xaml이라는 별도의 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>

이 사전을 사용하기 위해 다음과 같이 페이지의 사전과 병합합니다.

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

다음은 이 예제에서 수행되는 작업입니다. <Page.Resources>에서는 <ResourceDictionary>를 선언합니다. <Page.Resources>에 리소스를 추가하면 XAML 프레임워크에서 리소스 사전을 암시적으로 만들지만 이 예제에서는 아무 리소스 사전이 아니라 병합된 사전이 포함된 리소스 사전을 원합니다.

따라서 <ResourceDictionary>을 선언한 다음 <ResourceDictionary.MergedDictionaries> 컬렉션에 항목을 추가합니다 . 이러한 각 항목은 형식 <ResourceDictionary Source="Dictionary1.xaml"/>을 사용합니다. 둘 이상의 사전을 추가하려면 첫 번째 항목 뒤의 <ResourceDictionary Source="Dictionary2.xaml"/> 항목을 추가하기만 하면 됩니다.

<ResourceDictionary.MergedDictionaries>…</ResourceDictionary.MergedDictionaries> 다음, 필요에 따라 기본 사전에 추가 리소스를 넣을 수 있습니다. 일반 사전처럼 병합된 사전의 리소스를 사용합니다. 위의 예제에서 {StaticResource brush}은(는) 하위/병합된 사전(Dictionary1.xaml)에서 리소스를 찾는 반면 {StaticResource greeting}은(는) 기본 페이지 사전에서 리소스를 찾습니다.

리소스 조회 시퀀스에서는 해당 ResourceDictionary의 모든 기타 키 입력 리소스를 확인한 후에야 MergedDictionaries 사전을 확인합니다. 해당 수준을 검색한 후 조회가 병합된 사전에 도달하고 MergedDictionaries의 각 항목이 확인됩니다. 여러 병합된 사전이 있는 경우 이러한 사전은 MergedDictionaries 속성에 선언된 순서의 역순으로 검사. 다음 예제에서는 Dictionary2.xaml과 Dictionary1.xaml이 모두 동일한 키를 선언한 경우 MergedDictionaries 집합의 마지막 키이므로 Dictionary2.xaml의 키가 먼저 사용됩니다.

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

하나의 ResourceDictionary 범위 내에서 사전은 키 고유성을 위해 검사. 그러나 해당 범위는 다른 MergedDictionaries 파일의 다른 항목 간에 확장되지 않습니다.

조회 시퀀스의 조합과 병합된 사전 범위에서 고유한 키 적용 부족의 조합을 사용하여 ResourceDictionary 리소스의 대체 값 시퀀스를 만들 수 있습니다. 예를 들어 앱의 상태 및 사용자 기본 설정 데이터와 동기화되는 리소스 사전을 사용하여 시퀀스의 마지막 병합된 리소스 사전에 특정 브러시 색에 대한 사용자 기본 설정을 저장할 수 있습니다. 그러나 사용자 기본 설정이 없는 경우에는 이전 초기 MergedDictionaries 파일의 ResourceDictionary 리소스에 대해 동일한 키 문자열을 정의할 수 있으며, 대체 값으로 사용될 수 있습니다. 기본 리소스 사전에 제공하는 모든 값은 병합된 사전이 검사 전에 항상 있으므로 대체 기술을 사용하려는 경우, 기본 리소스 사전에서 해당 리소스를 정의하지 마세요.

테마 리소스 및 테마 사전

ThemeResourceStaticResource와 유사하지만 테마가 변경되면 리소스 조회가 다시 평가됩니다.

이 예제에서는 TextBlock의 포그라운드를 현재 테마의 값으로 설정합니다.

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

테마 사전은 사용자가 자신의 장치에서 현재 사용하고 있는 테마에 따라 달라지는 리소스를 보유하는 특수한 유형의 병합 사전입니다. 예를 들어 '밝은' 테마는 흰색 브러시를 사용하는 반면 '어두운' 테마는 어두운 색 브러시를 사용할 수 있습니다. 브러시는 확인되는 리소스를 변경하지만, 그렇지 않으면 브러시를 리소스로 사용하는 컨트롤의 컴퍼지션이 동일할 수 있습니다. 항목을 기본 사전에 병합하는 속성으로 MergedDictionaries를 사용하는 대신 고유한 템플릿 및 스타일에서 테마 전환 동작을 재현하려면 ThemeDictionaries 속성을 사용합니다.

ThemeDictionaries의 각 ResourceDictionary 요소에는 x:Key 값이 있어야 합니다. 값은 관련 테마의 이름을 지정하는 문자열입니다(예: 'Default', 'Dark', 'Light' 또는 'HighContrast'). 일반적으로 Dictionary1Dictionary2 이름이 같지만 값이 다른 리소스를 정의합니다.

여기서는 밝은 테마에 빨간색 텍스트를 사용하고 어두운 테마에는 파란색 텍스트를 사용합니다.

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

이 예제에서는 TextBlock의 포그라운드를 현재 테마의 값으로 설정합니다.

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

테마 사전의 경우 ThemeResource 마크업 확장을 사용하여 참조를 수행하고 시스템에서 테마 변경을 감지할 때마다 리소스 조회에 사용할 활성 사전이 동적으로 변경됩니다. 시스템에서 수행하는 조회 동작은 활성 테마를 특정 테마 사전의 x:Key 에 매핑하는 것을 기반으로 합니다.

테마 사전이 기본 XAML 디자인 리소스에서 구조화되는 방식을 검사하는 것이 유용할 수 있습니다. 이 리소스는 Windows 런타임 컨트롤에 기본적으로 사용하는 템플릿과 유사합니다. 텍스트 편집기 또는 IDE를 사용하여 \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK 버전>\Generic의 XAML 파일을 엽니다. generic.xaml에서 테마 사전이 먼저 정의되는 방법과 각 테마 사전이 동일한 키를 정의하는 방법을 확인합니다. 그런 다음 각 키는 테마 사전 외부에 있고 나중에 XAML에서 정의된 다양한 키 요소의 컴퍼지션 요소에서 참조됩니다. 또한 기본 컨트롤 템플릿이 아닌 테마 리소스와 추가 템플릿만 포함하는 디자인용 별도의 themeresources.xaml 파일도 있습니다. 테마 영역은 generic.xaml에서 볼 수 있는 것과 중복됩니다.

XAML 디자인 도구를 사용하여 스타일 및 템플릿의 복사본을 편집하는 경우, 디자인 도구는 XAML 디자인 리소스 사전에서 섹션을 추출하고 앱 및 프로젝트의 일부인 XAML 사전 요소의 로컬 복사본으로 배치합니다.

자세한 내용과 XAML을 사용하는 UWP 앱에서 사용할 수 있는 테마별 시스템 리소스 목록은 XAML 테마 리소스를 참조하세요.

XAML 리소스 참조에 대한 조회 동작

조회 동작 은 XAML 리소스 시스템에서 XAML 리소스를 찾는 방법을 설명하는 용어입니다. 조회는 키가 앱의 XAML 어딘가에서 XAML 리소스 참조로 참조될 때 발생합니다. 첫째, 리소스 시스템은 범위에 따라 리소스가 존재하기 위해 검사 위치에 대해 예측 가능한 동작을 가합니다. 초기 범위에서 리소스를 찾을 수 없는 경우, 범위가 확장됩니다. 조회 동작은 앱 또는 시스템에서 XAML 리소스를 정의할 수 있는 위치 및 범위 전체에서 계속됩니다. 가능한 모든 리소스 조회 시도가 실패하면 오류가 자주 발생합니다. 일반적으로 개발 프로세스 중, 이러한 오류를 제거할 수 있습니다.

XAML 리소스 참조에 대한 조회 동작은 실제 사용량이 적용되는 개체와 자체 Resources 속성으로 시작합니다. 해당 위치에 ResourceDictionary가 있는 경우 이 ResourceDictionary에서 요청된 키가 있는 항목을 확인합니다. 이 첫 번째 수준의 조회는 일반적으로 동일한 개체에서 리소스를 정의한 다음 참조하지 않으므로 거의 관련이 없습니다. 실제로 Resources 속성은 여기에 없는 경우가 많습니다. XAML의 거의 모든 위치에서 XAML 리소스 참조를 만들 수 있습니다. FrameworkElement 하위 클래스의 속성으로 제한되지 않습니다.

그런 다음 조회 시퀀스는 앱의 런타임 개체 트리에서 다음 상위 개체를 검사합니다. FrameworkElement.Resources가 존재하고 ResourceDictionary를 보유하는 경우 지정된 키 문자열이 있는 사전 항목이 요청됩니다. 리소스가 발견되면 조회 시퀀스가 중지되고 참조가 만들어진 위치에 개체가 제공됩니다. 그렇지 않으면 조회 동작이 개체 트리 루트를 향해 다음 상위 수준으로 진행됩니다. XAML의 루트 요소에 도달할 때까지 검색이 재귀적으로 계속되어 가능한 모든 즉시 리소스 위치를 검색합니다.

참고

이러한 리소스 조회 동작을 활용하기 위해 그리고 XAML 태그 스타일 규칙으로 인해 일반적으로 페이지의 루트 수준에서 모든 즉시 실행 리소스를 정의합니다.

요청된 리소스가 즉시 리소스에 없는 경우 다음 조회 단계는 Application.Resources 속성을 검사하는 것입니다. Application.Resources 는 앱의 탐색 구조에서 여러 페이지에서 참조하는 앱별 리소스를 배치하는 가장 좋은 장소입니다.

중요

ResourceDictionary에 추가되는 리소스의 순서는 적용되는 순서에 영향을 줍니다. XamlControlsResources 사전은 많은 기본 리소스 키를 재정의하므로 앱의 다른 사용자 지정 스타일 또는 리소스를 재정의하지 않도록 먼저 Application.Resources에 추가해야 합니다.

컨트롤 템플릿은 참조 조회에서 테마 사전이라는 다른 가능한 위치를 갖습니다. 테마 사전은 ResourceDictionary 요소를 루트로 사용하는 단일 XAML 파일입니다. 테마 사전은 Application.Resources에서 병합된 사전일 수 있습니다. 테마 사전은 템플릿 기반 사용자 지정 컨트롤에 대한 컨트롤별 테마 사전일 수도 있습니다.

마지막으로 플랫폼 리소스에 대한 리소스 조회가 있습니다. 플랫폼 리소스에는 각 시스템 UI 테마에 대해 정의되고 Windows 런타임 앱에서 UI에 사용하는 모든 컨트롤의 기본 모양을 정의하는 컨트롤 템플릿이 포함됩니다. 플랫폼 리소스에는 시스템 전체 모양 및 테마와 관련된 명명된 리소스 집합도 포함됩니다. 이러한 리소스는 기술적으로 MergedDictionaries 항목이므로 앱이 로드되면 XAML 또는 코드에서 조회할 수 있습니다. 예를 들어 시스템 테마 리소스에는 앱 텍스트 색을 운영 체제 및 사용자 기본 설정에서 가져온 시스템 창의 텍스트 색과 일치시키는 Color 정의를 제공하는 'SystemColorWindowTextColor'라는 리소스가 포함됩니다. 앱의 다른 XAML 스타일은 이 스타일을 참조하거나 코드에서 리소스 조회 값을 가져와서 예제의 경우 Color로 캐스팅할 수 있습니다.

자세한 내용과 XAML을 사용하는 Windows 앱에서 사용할 수 있는 테마별 시스템 리소스의 목록을 보려면 XAML 테마 리소스를 참조하세요.

이러한 위치에서 요청된 키를 찾을 수 없는 경우, XAML 구문 분석 오류/예외가 발생합니다. 특정 상황에서 XAML 구문 분석 예외는 XAML 태그 컴파일 작업 또는 XAML 디자인 환경에서 검색되지 않는 런타임 예외일 수 있습니다.

리소스 사전에 대한 계층화된 조회 동작으로 인해 각 리소스가 다른 수준에서 정의되는 한 각 리소스가 키와 동일한 문자열 값을 갖는 여러 리소스 항목을 의도적으로 정의할 수 있습니다. 즉, 키가 지정된 ResourceDictionary 내에서 고유해야 하지만 고유성 요구 사항이 조회 동작 시퀀스 전체로 확장되지는 않습니다. 조회하는 동안 성공적으로 검색된 첫 번째 개체만 XAML 리소스 참조에 사용된 다음 조회가 중지됩니다. 이 동작을 사용하여 앱의 XAML 내의 다양한 위치에서 키로 동일한 XAML 리소스를 요청하지만 XAML 리소스 참조가 만들어진 범위와 특정 조회가 작동하는 방식에 따라 다른 리소스를 다시 가져올 수 있습니다.

ResourceDictionary 내에서 참조 전달

특정 리소스 사전 내의 XAML 리소스 참조는 키로 이미 정의된 리소스를 참조해야 하며, 해당 리소스는 리소스 참조 앞에 어휘적으로 표시되어야 합니다. XAML 리소스 참조로 정적 리소스 참조를 확인할 수 없습니다. 이러한 이유로 다른 리소스 내에서 XAML 리소스 참조를 사용하는 경우 다른 리소스에서 사용되는 리소스가 먼저 리소스 사전에서 정의되도록 리소스 사전 구조를 디자인해야 합니다.

앱 수준에서 정의된 리소스는 즉시 리소스를 참조할 수 없습니다. 이는 앱 리소스가 실제로 먼저 처리되기 때문에(앱이 처음 시작될 때 및 탐색 페이지 콘텐츠가 로드되기 전에) 정방향 참조를 시도하는 것과 같습니다. 그러나 즉각적인 리소스는 앱 리소스에 대한 참조를 만들 수 있으며 이는 전방 참조 상황을 방지하는 데 유용한 기술일 수 있습니다.

XAML 리소스를 공유할 수 있어야 합니다.

개체가 ResourceDictionary에 있으려면 공유 가능해야 합니다.

앱의 개체 트리가 생성되고 런타임에 사용될 때 트리의 여러 위치에 개체가 존재할 수 없으므로 공유 가능해야 합니다. 내부적으로 리소스 시스템은 각 XAML 리소스가 요청되면 앱의 개체 그래프에 사용할 리소스 값의 복사본을 만듭니다.

일반적으로 ResourceDictionary 및 Windows 런타임 XAML은 공유 가능한 사용을 위해 다음 개체를 지원합니다.

필요한 구현 패턴을 따르는 경우 사용자 지정 형식을 공유 가능한 리소스로 사용할 수도 있습니다. 지원 코드(또는 포함하는 런타임 구성 요소)에서 이러한 클래스를 정의한 다음 XAML에서 해당 클래스를 리소스로 인스턴스화합니다. 예를 들어 데이터 바인딩을 위한 개체 데이터 원본 및 IValueConverter 구현이 있습니다.

XAML 파서가 클래스를 인스턴스화하는 데 사용하기 때문에 사용자 지정 형식에는 기본 생성자가 있어야 합니다. UIElement는 공유할 수 없으므로 리소스로 사용되는 사용자 지정 형식의 상속에 UIElement 클래스를 포함할 수 없습니다. 이 클래스는 항상 런타임 앱의 개체 그래프에서 한 위치에 있는 단일 UI 요소만 나타냅니다.

UserControl 사용 범위

UserControl 요소는 정의 범위 및 사용 범위의 고유 개념을 가지고 있으므로 리소스 조회 동작에 특별한 상황이 있습니다. 정의 범위에서 XAML 리소스 참조를 만드는 UserControl은 자체 정의 범위 조회 시퀀스 내에서 해당 리소스의 조회를 지원할 수 있어야 합니다. 즉, 앱 리소스에 액세스할 수 없습니다. UserControl 사용 범위에서 리소스 참조는 로드된 개체 트리의 개체에서 만든 다른 리소스 참조와 마찬가지로 해당 사용 페이지 루트에 대한 조회 시퀀스 내에 있는 것으로 간주되며 앱 리소스에 액세스할 수 있습니다.

ResourceDictionary 및 XamlReader.Load

ResourceDictionaryXamlReader.Load 메서드에 대한 XAML 입력의 루트 또는 일부로 사용할 수 있습니다. 이러한 모든 참조가 로드를 위해 제출된 XAML에 완전히 자체 포함된 경우 해당 XAML에 XAML 리소스 참조를 포함할 수도 있습니다. XamlReader.LoadApplication.Resources는 물론 다른 ResourceDictionary 개체도 인식하지 못하는 컨텍스트에서 XAML을 구문 분석합니다. 또한 XamlReader.Load에 제출된 XAML 내에서 {ThemeResource}을(를) 사용하지마세요.

코드에서 ResourceDictionary 사용

ResourceDictionary에 대한 대부분의 시나리오는 XAML에서만 처리됩니다. UI 정의 파일에서 ResourceDictionary 컨테이너 및 리소스를 XAML 파일 또는 XAML 노드 집합으로 선언합니다. 그런 다음 XAML 리소스 참조를 사용하여 XAML의 다른 부분에서 해당 리소스를 요청합니다. 그러나 앱이 실행되는 동안 실행되는 코드를 사용하여 앱이 ResourceDictionary의 콘텐츠를 조정하거나 적어도 ResourceDictionary의 콘텐츠를 쿼리하여 리소스가 이미 정의되어 있는지 확인하는 특정 시나리오가 있습니다. 이러한 코드 호출은 ResourceDictionary 인스턴스에서 수행되므로 먼저 하나의 항목, 즉 FrameworkElement.Resources를 가져와 개체 트리에서 즉시 실행 ResourceDictionary를 검색하거나 Application.Current.Resources을(를) 검색해야 합니다.

C# 또는 Microsoft Visual Basic 코드에서 인덱서(Item)를 사용하여 특정 ResourceDictionary의 리소스를 참조할 수 있습니다. ResourceDictionary는 문자열 키 사전이므로 인덱서는 정수 인덱스 대신 문자열 키를 사용합니다. Visual C++ 구성 요소 확장(C++/CX) 코드에서 Lookup을 사용합니다.

코드를 사용하여 ResourceDictionary를 검사하거나 변경하는 경우 Lookup 또는 Item과 같은 API 동작은 즉시 리소스에서 앱 리소스로 트래버스되지 않습니다. 즉, XAML 페이지가 로드될 때만 발생하는 XAML 파서 동작입니다. 런타임에 키 범위는 당시 사용 중인 ResourceDictionary 인스턴스에 자체 포함됩니다. 그러나 해당 범위는 MergedDictionaries로 확장됩니다.

또한 ResourceDictionary에 없는 키를 요청하는 경우 오류가 발생하지 않고 단순히 반환 값이 null로 제공될 수 있습니다. 하지만 반환된 null 을 값으로 사용하려고 하면 여전히 오류가 발생할 수 있습니다. 이 오류는 ResourceDictionary 호출이 아닌 속성의 setter에서 발생합니다. 오류를 방지할 수 있는 유일한 방법은 속성이 null을 유효한 값으로 수락한 경우입니다. 이 동작이 XAML 구문 분석 시간에 XAML 조회 동작과 어떻게 대조되는지 알아봅니다. 구문 분석 시 XAML에서 제공된 키를 해결하지 못하면 속성이 null을 수락할 수 있는 경우에도 XAML 구문 분석 오류가 발생합니다.

병합된 리소스 사전은 런타임에 병합된 사전을 참조하는 기본 리소스 사전의 인덱스 범위에 포함됩니다. 다시 말해 기본 사전의 Item 또는 Lookup을 사용하여 병합된 사전에 실제로 정의된 모든 개체를 찾을 수 있습니다. 이 경우 조회 동작은 구문 분석 시간 XAML 조회 동작과 유사합니다. 병합된 사전에 각각 동일한 키를 가진 여러 개체가 있는 경우 마지막으로 추가한 사전의 개체가 반환됩니다.

Add(C# 또는 Visual Basic) 또는 Insert(C++/CX)를 호출하여 기존 ResourceDictionary에 항목을 추가할 수 있습니다. 즉시 리소스 또는 앱 리소스에 항목을 추가할 수 있습니다. 이러한 API 호출 중 하나에는 ResourceDictionary의 각 항목에 키가 있어야 한다는 요구 사항을 충족하는 키가 필요합니다. 그러나 런타임에 ResourceDictionary에 추가하는 항목은 XAML 리소스 참조와 관련이 없습니다. XAML 리소스 참조에 필요한 조회는 앱이 로드될 때 XAML이 처음 구문 분석되거나 테마 변경이 검색될 때 발생합니다. 런타임에 컬렉션에 추가된 리소스는 사용할 수 없었고 ResourceDictionary를 변경해도 해당 리소스의 값을 변경하더라도 이미 검색된 리소스가 무효화되지 않습니다.

런타임에 ResourceDictionary에서 항목을 제거하거나 일부 또는 모든 항목의 복사본을 만들거나 다른 작업을 수행할 수도 있습니다. ResourceDictionary에 대한 멤버 목록은 사용할 수 있는 API를 나타냅니다. ResourceDictionary에 기본 컬렉션 인터페이스를 지원하는 예상 API가 있으므로 C# 또는 Visual Basic 및 C++/CX 사용 여부에 따라 해당 API 옵션이 달라집니다.

ResourceDictionary 및 현지화

XAML ResourceDictionary 는 처음에 현지화할 문자열을 포함할 수 있습니다. 그렇다면 이러한 문자열을 ResourceDictionary 대신 프로젝트 리소스로 저장합니다. 문자열을 XAML에서 꺼내고 대신 소유 요소에 x:Uid directive 값을 제공합니다. 그런 다음 리소스 파일에서 리소스를 정의합니다. XUIDValue 형식으로 리소스 이름을 제공합니다.PropertyName 및 현지화해야 하는 문자열의 리소스 값입니다.

사용자 지정 리소스 조회

고급 시나리오의 경우 이 항목에 설명된 XAML 리소스 참조 조회 동작과 다른 동작을 가질 수 있는 클래스를 구현할 수 있습니다. 이렇게 하려면 CustomXamlResourceLoader 클래스를 구현한 다음, StaticResource 또는 ThemeResource를 사용하는 대신 리소스 참조에 CustomResource 태그 확장을 사용하여 해당 동작에 액세스할 수 있습니다. 대부분의 앱에는 이를 필요로 하는 시나리오가 없습니다. 자세한 내용은 CustomXamlResourceLoader를 참조하십시오.