다음을 통해 공유


ResourceDictionary 및 XAML 리소스 참조

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

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

필수 조건

XAML 마크업에 대한 확실한 이해. 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} - "greeting" 키로 리소스를 조회하여 TextBlockText 속성에 할당합니다.

참고ResourceDictionary와 관련된 개념을 앱 패키지를 생성하는 코드 프로젝트를 구조화하는 컨텍스트에서 설명하는 Resource 빌드 작업, 리소스(.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"사용하여 정의된 문자열입니다. 그러나 키를 지정하는 몇 가지 다른 방법이 있습니다.

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

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

여기서 Style에는 typeof(Button)라는 암시적 키가 있으며, 페이지 아래쪽에 있는 ButtonStyle 속성을 지정하지 않았기 때문에 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에 로컬 리소스 사전을 추가할 수 있습니다.

여기서는 페이지테두리 모두 리소스 사전이 있으며 둘 다 "greeting"이라는 리소스가 있습니다. 'textBlock2'라는 TextBlock테두리안에 있으므로, 리소스를 찾을 때 먼저 Border의 리소스를, 다음으로 Page의 리소스를, 마지막으로 애플리케이션의 리소스를 검색합니다. 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>을 선언합니다. XAML 프레임워크는 <Page.Resources>; 에 리소스를 추가할 때 리소스 사전을 암시적으로 만듭니다. 그러나 이 경우 리소스 사전만 원하지 않고 병합된 사전이 포함된 사전을 원합니다.

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

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

리소스 조회 시퀀스에서 MergedDictionaries 사전은 해당 ResourceDictionary다른 모든 키 리소스를 확인한 후에만 확인됩니다. 해당 수준을 검색한 후, 조회는 병합된 사전을 탐색하며 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 테마 리소스 참조하세요.

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 또는 코드에서 조회할 수 있습니다. 예를 들어 시스템 테마 리소스에는 앱 텍스트 색을 운영 체제 및 사용자 기본 설정에서 가져온 시스템 창의 텍스트 색과 일치시키는 정의를 제공하는 "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.Load는 다른 ResourceDictionary 개체나Application.Resources 조차 인식하지 못하는 컨텍스트에서 XAML을 구문 분석합니다. 제출된 XAML을 {ThemeResource}에서 사용할 때, 을 사용하지 마세요.

코드에서 ResourceDictionary 활용하기

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

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

코드를 사용하여 ResourceDictionary를 검사하거나 변경할 때, Lookup 또는 Item과 같은 API의 동작은 즉시 리소스에서 앱 리소스로 탐색하지 않습니다. 이것은 XAML 페이지가 로드될 때만 발생하는 XAML 파서의 동작입니다. 런타임 시, 키의 범위는 그 당시 사용 중인 ResourceDictionary 인스턴스에 자체적으로 한정됩니다. 그러나 그 범위는 MergedDictionaries로 확장되기는 합니다.

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

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

추가(C# 또는 Visual Basic) 또는 삽입(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 지시문 값을 제공합니다. 그런 다음 리소스 파일에서 리소스를 정의합니다. 리소스 이름을 XUIDValue.PropertyName 형식으로 제공하고, 지역화해야 할 문자열의 리소스 값을 제공합니다.

사용자 지정 리소스 조회

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