WPF의 Pack URI

WPF(Windows Presentation Foundation)에서는 URI(Uniform Resource Identifier)를 사용하여 다음을 비롯한 여러 가지 방법으로 파일을 식별하고 로드합니다.

  • 애플리케이션을 처음으로 시작할 때 표시되는 UI(사용자 인터페이스) 지정

  • 이미지 로드

  • 페이지 탐색

  • 비실행 데이터 파일 로드

또한 다음을 비롯한 다양한 위치에서 파일을 식별하고 로드하는 데 URI를 사용할 수도 있습니다.

  • 현재 어셈블리입니다.

  • 참조된 어셈블리

  • 어셈블리에 상대적인 위치

  • 애플리케이션의 원본 사이트

이러한 위치에서 이러한 형식의 파일을 식별하고 로드하는 일관성 있는 메커니즘을 제공하기 위해 WPF는 Pack URI 체계의 확장성을 이용합니다. 이 항목에서는 태그와 코드에서 Pack URI를 사용하는 방법을 보여 주기 전에 이 체계를 개략적으로 소개하고 다양한 시나리오에서 Pack URI를 구성하는 방법을 설명하며 절대 및 상대 URI와 URI 확인에 대해 설명합니다.

Pack URI 체계

Pack URI 체계는 콘텐츠를 구성하고 식별하는 모델을 설명하는 OPC(Open Packaging Conventions) 사양에서 사용됩니다. 이 모델의 핵심 요소는 패키지와 파트입니다. 여기서 패키지는 하나 이상의 논리적 파트에 대한 논리적 컨테이너입니다. 다음 그림에서는 이 개념을 보여 줍니다.

패키지 및 파트 다이어그램

파트를 식별하기 위해 OPC 사양에서는 RFC 2396(URI(Uniform Resource Identifier): 제네릭 구문)의 확장성을 이용하여 Pack URI 체계를 정의합니다.

URI로 지정되는 이 체계는 접두사로 정의됩니다. http, ftp 및 file은 잘 알려진 접두사의 예입니다. Pack URI 체계는 “pack”을 해당 구조로 사용하며 인증 기관과 경로의 두 가지 구성 요소를 포함합니다. 다음은 Pack URI의 형식입니다.

pack://authority/path

authority는 파트가 포함된 패키지의 형식을 지정하고 path는 패키지 내에서 파트의 위치를 지정합니다.

다음 그림에서는 이 개념을 보여 줍니다.

패키지, 권한 및 경로의 관계

패키지와 파트는 애플리케이션 및 파일과 유사합니다. 즉, 애플리케이션(패키지)은 다음을 비롯한 하나 이상의 파일(파트)을 포함할 수 있습니다.

  • 로컬 어셈블리로 컴파일되는 리소스 파일

  • 참조된 어셈블리로 컴파일되는 리소스 파일

  • 참조하는 어셈블리로 컴파일되는 리소스 파일

  • 콘텐츠 파일

  • 원본 사이트 파일

이러한 형식의 파일에 액세스할 수 있도록 WPF는 두 가지 권한인 application:/// 및 siteoforigin:///을 지원합니다. application:/// 인증 기관은 리소스 및 콘텐츠 파일을 비롯하여 컴파일 시 알려진 애플리케이션 데이터 파일을 식별합니다. siteoforigin:/// 인증 기관은 원본 사이트 파일을 식별합니다. 다음 그림에서는 각 인증 기관의 범위를 보여 줍니다.

Pack URI 다이어그램

참고

Pack URI의 인증 기관 구성 요소는 패키지를 가리키는 포함된 URI이며 RFC 2396을 따라야 합니다. 또한 “/” 문자를 “,” 문자로 바꾸고 “%” 및 “?” 같은 예약 문자는 이스케이프해야 합니다. 자세한 내용은 OPC를 참조하세요.

다음 단원에서는 이 두 인증 기관과 리소스, 콘텐츠 및 원본 사이트 파일을 식별하는 적절한 경로를 조합하여 Pack URI를 구성하는 방법에 대해 설명합니다.

리소스 파일 Pack URI

리소스 파일은 MSBuild Resource 항목으로 구성되며 어셈블리로 컴파일됩니다. WPF는 로컬 어셈블리로 컴파일되거나 로컬 어셈블리에서 참조되는 어셈블리로 컴파일되는 리소스 파일을 식별하는 데 사용할 수 있는 Pack URI의 생성을 지원합니다.

로컬 어셈블리 리소스 파일

로컬 어셈블리로 컴파일되는 리소스 파일에 대한 Pack URI는 다음 인증 기관과 경로를 사용합니다.

  • 인증 기관: application:///

  • 경로: 로컬 어셈블리 프로젝트 폴더 루트에 상대적인 경로를 포함한 리소스 파일의 이름

다음 예제에서는 로컬 어셈블리의 프로젝트 폴더 루트에 있는 XAML 리소스 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/ResourceFile.xaml

다음 예제에서는 로컬 어셈블리의 프로젝트 폴더 하위 폴더에 있는 XAML 리소스 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/Subfolder/ResourceFile.xaml

참조된 어셈블리 리소스 파일

참조된 어셈블리로 컴파일되는 리소스 파일에 대한 Pack URI는 다음 인증 기관과 경로를 사용합니다.

  • 인증 기관: application:///

  • 경로: 참조된 어셈블리로 컴파일되는 리소스 파일의 이름. 경로는 다음 형식을 따라야 합니다.

    AssemblyShortName{;Version]{;PublicKey];component/Path

    • AssemblyShortName: 참조된 어셈블리에 대한 약식 이름

    • ;Version[옵션]: 리소스 파일을 포함하는 참조된 어셈블리의 버전. 동일한 약식 이름을 갖는 두 개 이상의 참조된 어셈블리가 로드된 경우 사용됩니다.

    • ;PublicKey[옵션]: 참조된 어셈블리를 서명하는 데 사용된 공개 키. 동일한 약식 이름을 갖는 두 개 이상의 참조된 어셈블리가 로드된 경우 사용됩니다.

    • ;component: 참조되는 어셈블리가 로컬 어셈블리에서 참조된다는 것을 지정

    • /Path: 참조된 어셈블리 프로젝트 폴더의 루트에 상대적인 경로를 포함한 리소스 파일의 이름

다음 예제에서는 참조된 어셈블리의 프로젝트 폴더 루트에 있는 XAML 리소스 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml

다음 예제에서는 참조된 어셈블리의 프로젝트 폴더 하위 폴더에 있는 XAML 리소스 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

다음 예제에서는 참조된 버전별 어셈블리의 프로젝트 폴더 루트 폴더에 있는 XAML 리소스 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml

참조된 어셈블리 리소스 파일에 대한 Pack URI 구문은 application:/// 인증 기관에만 사용할 수 있습니다. 예를 들어 다음은 WPF에서 지원되지 않습니다.

pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml

콘텐츠 파일 Pack URI

콘텐츠 파일에 대한 Pack URI는 다음 인증 기관과 경로를 사용합니다.

  • 인증 기관: application:///

  • 경로: 애플리케이션의 주 실행 가능 어셈블리의 파일 시스템 위치에 상대적인 경로를 포함한 콘텐츠 파일의 이름

다음 예제에서는 실행 가능 어셈블리와 동일한 폴더에 있는 XAML 콘텐츠 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/ContentFile.xaml

다음 예제에서는 애플리케이션의 실행 가능 어셈블리에 상대적인 하위 폴더에 있는 XAML 콘텐츠 파일에 대한 Pack URI를 보여 줍니다.

pack://application:,,,/Subfolder/ContentFile.xaml

참고

HTML 콘텐츠 파일은 탐색할 수 없습니다. URI 체계는 원본 사이트에 위치한 HTML 파일에 대한 탐색만 지원합니다.

원본 사이트 Pack URI

원본 사이트 파일에 대한 Pack URI는 다음 인증 기관과 경로를 사용합니다.

  • 인증 기관: siteoforigin:///

  • 경로: 실행 가능 어셈블리가 시작된 위치에 상대적인 경로를 포함한 원본 사이트 파일의 이름

다음 예제에서는 실행 가능 어셈블리가 시작된 위치에 저장되어 있는 XAML 원본 사이트 파일에 대한 Pack URI를 보여 줍니다.

pack://siteoforigin:,,,/SiteOfOriginFile.xaml

다음 예제에서는 애플리케이션의 실행 가능 어셈블리가 시작된 위치에 상대적인 하위 폴더에 저장되어 있는 XAML 원본 사이트 파일에 대한 Pack URI를 보여 줍니다.

pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml

페이지 파일

MSBuild Page 항목으로 구성된 XAML 파일은 리소스 파일과 동일한 방식으로 어셈블리로 컴파일됩니다. 따라서 리소스 파일에 대한 Pack URI를 사용하여 MSBuild Page 항목을 식별할 수 있습니다.

일반적으로 MSBuild Page 항목으로 구성되는 XAML 파일 형식에는 해당 루트 요소로 다음 중 하나가 포함됩니다.

절대 Pack URI와 상대 Pack URI 비교

정규화된 Pack URI는 체계, 인증 기관 및 경로를 포함하며 절대 Pack URI로 간주됩니다. 개발자가 쉽게 사용할 수 있도록 일반적으로 XAML 요소에서는 경로만 포함하는 상대 Pack URI를 사용하여 해당 특성을 설정할 수 있습니다.

예를 들어 로컬 어셈블리에 있는 리소스 파일에 대한 다음과 같은 절대 Pack URI를 가정해 봅니다.

pack://application:,,,/ResourceFile.xaml

이 리소스 파일을 참조하는 상대 Pack URI는 다음과 같습니다.

/ResourceFile.xaml

참고

원본 사이트 파일은 어셈블리와 연결되어 있지 않기 때문에 절대 Pack URI로만 참조할 수 있습니다.

기본적으로 상대 Pack URI는 참조가 들어 있는 태그나 코드의 위치에 상대적인 것으로 간주됩니다. 하지만 앞에 백슬래시가 사용되면 상대 Pack URI 참조는 애플리케이션 루트에 상대적인 것으로 간주됩니다. 예를 들어 다음과 같은 프로젝트 구조를 가정해 봅니다.

App.xaml

Page2.xaml

\SubFolder

+ Page1.xaml

+ Page2.xaml

Page1.xaml에 Root\SubFolder\Page2.xaml을 참조하는 URI가 들어 있다면 해당 참조에서 다음과 같은 상대 Pack URI를 사용할 수 있습니다.

Page2.xaml

Page1.xaml에 Root\Page2.xaml을 참조하는 URI가 들어 있다면 해당 참조에서 다음과 같은 상대 Pack URI를 사용할 수 있습니다.

/Page2.xaml

Pack URI 확인

Pack URI의 형식에서는 서로 다른 파일 형식에 대한 Pack URI가 동일하게 나타날 수 있습니다. 예를 들어 다음과 같은 절대 Pack URI를 가정해 봅니다.

pack://application:,,,/ResourceOrContentFile.xaml

이 절대 Pack URI는 로컬 어셈블리나 콘텐츠 파일의 리소스 파일을 참조할 수 있습니다. 다음과 같은 상대 URI의 경우에도 마찬가지입니다.

/ResourceOrContentFile.xaml

Pack URI가 참조하는 파일 형식을 확인하기 위해서 WPF는 다음과 같은 경험적 접근을 통해 로컬 어셈블리와 콘텐츠 파일에서 리소스 파일에 대한 URI를 확인합니다.

  1. Pack URI와 일치하는 AssemblyAssociatedContentFileAttribute 특성에 대한 어셈블리 메타데이터를 검색합니다.

  2. AssemblyAssociatedContentFileAttribute 특성이 있으면 Pack URI의 경로는 콘텐츠 파일을 참조합니다.

  3. AssemblyAssociatedContentFileAttribute 특성이 없으면 로컬 어셈블리로 컴파일되는 리소스 파일 집합을 검색합니다.

  4. Pack URI 경로와 일치하는 리소스 파일이 있으면 Pack URI의 경로는 리소스 파일을 참조합니다.

  5. 리소스 파일이 없으면 내부적으로 생성된 Uri가 무효가 됩니다.

URI 확인은 다음을 참조하는 URI에는 적용되지 않습니다.

  • 참조되는 어셈블리의 콘텐츠 파일: WPF는 이러한 파일 형식을 지원하지 않습니다.

  • 참조되는 어셈블리의 포함된 파일: 참조되는 어셈블리의 이름과 ;component 접미사를 모두 포함하기 때문에 이 파일을 식별하는 URI는 고유합니다.

  • 원본 사이트 파일: 이 파일은 siteoforigin:/// 인증 기관을 포함하는 Pack URI로 식별할 수 있는 유일한 파일이기 때문에 이 파일을 식별하는 URI는 고유합니다.

Pack URI 확인에서 허용하는 한 가지 단순화는 코드가 리소스 및 콘텐츠 파일 위치와 다소 독립적일 수 있다는 것입니다. 예를 들어 로컬 어셈블리에 콘텐츠 파일로 다시 구성되는 리소스 파일이 있는 경우 Pack URI를 사용하는 코드와 마찬가지로 해당 리소스에 대한 Pack URI가 동일하게 유지됩니다.

Pack URI를 사용한 프로그래밍

많은 WPF 클래스가 Pack URI로 설정할 수 있는 다음과 같은 속성을 구현합니다.

이러한 속성을 태그와 코드 모두에서 설정할 수 있습니다. 이 섹션에서는 두 경우에 대한 기본 구조를 설명한 다음 일반적인 시나리오 예제를 보여 줍니다.

태그에서 Pack URI 사용

Pack URI로 특성의 요소를 설정하여 Pack URI를 태그에 지정합니다. 예를 들면 다음과 같습니다.

<element attribute="pack://application:,,,/File.xaml" />

표 1에서는 태그에 지정할 수 있는 다양한 절대 Pack URI를 보여 줍니다.

표 1: 태그의 절대 Pack URI

파일 절대 Pack URI
리소스 파일 - 로컬 어셈블리 "pack://application:,,,/ResourceFile.xaml"
하위 폴더의 리소스 파일 - 로컬 어셈블리 "pack://application:,,,/Subfolder/ResourceFile.xaml"
리소스 파일 - 참조된 어셈블리 "pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml"
참조된 어셈블리의 하위 폴더에 있는 리소스 파일 "pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
버전이 있는 참조된 어셈블리의 리소스 파일 "pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml"
콘텐츠 파일 "pack://application:,,,/ContentFile.xaml"
하위 폴더의 콘텐츠 파일 "pack://application:,,,/Subfolder/ContentFile.xaml"
원본 사이트 파일 "pack://siteoforigin:,,,/SOOFile.xaml"
하위 폴더의 원본 사이트 파일 "pack://siteoforigin:,,,/Subfolder/SOOFile.xaml"

표 2에서는 태그에 지정할 수 있는 다양한 상대 Pack URI를 보여 줍니다.

표 2: 태그의 상대 Pack URI

파일 상대 Pack URI
로컬 어셈블리의 리소스 파일 "/ResourceFile.xaml"
로컬 어셈블리의 하위 폴더에 있는 리소스 파일 "/Subfolder/ResourceFile.xaml"
참조된 어셈블리의 리소스 파일 "/ReferencedAssembly;component/ResourceFile.xaml"
참조된 어셈블리의 하위 폴더에 있는 리소스 파일 "/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
콘텐츠 파일 "/ContentFile.xaml"
하위 폴더의 콘텐츠 파일 "/Subfolder/ContentFile.xaml"

코드에서 Pack URI 사용

Uri 클래스를 인스턴스화하고 Pack URI를 생성자에 매개 변수로 전달하여 코드에서 Pack URI를 지정합니다. 다음 예제에 이 내용이 나와 있습니다.

Uri uri = new Uri("pack://application:,,,/File.xaml");

기본적으로 Uri 클래스는 Pack URI가 절대라고 가정합니다. 따라서 Uri 클래스의 인스턴스가 상대 Pack URI로 생성되면 예외가 발생합니다.

Uri uri = new Uri("/File.xaml");

다행히 Uri 클래스 생성자의 Uri(String, UriKind) 오버로드가 UriKind 형식의 매개 변수를 받아들이므로 Pack URI가 절대인지 상대인지를 지정할 수 있습니다.

// Absolute URI (default)
Uri absoluteUri = new Uri("pack://application:,,,/File.xaml", UriKind.Absolute);
// Relative URI
Uri relativeUri = new Uri("/File.xaml",
                        UriKind.Relative);

제공된 Pack URI가 절대인지 상대인지 확실히 아는 경우에는 Absolute 또는 Relative만 지정해야 합니다. 사용자가 런타임에 Pack URI를 입력하는 경우와 같이 사용되는 Pack URI의 형식을 모르는 경우에는 RelativeOrAbsolute를 대신 사용합니다.

// Relative or Absolute URI provided by user via a text box
TextBox userProvidedUriTextBox = new TextBox();
Uri uri = new Uri(userProvidedUriTextBox.Text, UriKind.RelativeOrAbsolute);

표 3에서는 System.Uri를 사용하여 코드에 지정할 수 있는 다양한 상대 Pack URI를 보여 줍니다.

표 3: 코드의 절대 Pack URI

파일 절대 Pack URI
리소스 파일 - 로컬 어셈블리 Uri uri = new Uri("pack://application:,,,/ResourceFile.xaml", UriKind.Absolute);
하위 폴더의 리소스 파일 - 로컬 어셈블리 Uri uri = new Uri("pack://application:,,,/Subfolder/ResourceFile.xaml", UriKind.Absolute);
리소스 파일 - 참조된 어셈블리 Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Absolute);
참조된 어셈블리의 하위 폴더에 있는 리소스 파일 Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Absolute);
버전이 있는 참조된 어셈블리의 리소스 파일 Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml", UriKind.Absolute);
콘텐츠 파일 Uri uri = new Uri("pack://application:,,,/ContentFile.xaml", UriKind.Absolute);
하위 폴더의 콘텐츠 파일 Uri uri = new Uri("pack://application:,,,/Subfolder/ContentFile.xaml", UriKind.Absolute);
원본 사이트 파일 Uri uri = new Uri("pack://siteoforigin:,,,/SOOFile.xaml", UriKind.Absolute);
하위 폴더의 원본 사이트 파일 Uri uri = new Uri("pack://siteoforigin:,,,/Subfolder/SOOFile.xaml", UriKind.Absolute);

표 4에서는 System.Uri를 사용하여 코드에 지정할 수 있는 다양한 상대 Pack URI를 보여 줍니다.

표 4: 코드의 상대 Pack URI

파일 상대 Pack URI
리소스 파일 - 로컬 어셈블리 Uri uri = new Uri("/ResourceFile.xaml", UriKind.Relative);
하위 폴더의 리소스 파일 - 로컬 어셈블리 Uri uri = new Uri("/Subfolder/ResourceFile.xaml", UriKind.Relative);
리소스 파일 - 참조된 어셈블리 Uri uri = new Uri("/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Relative);
하위 폴더의 리소스 파일 - 참조된 어셈블리 Uri uri = new Uri("/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Relative);
콘텐츠 파일 Uri uri = new Uri("/ContentFile.xaml", UriKind.Relative);
하위 폴더의 콘텐츠 파일 Uri uri = new Uri("/Subfolder/ContentFile.xaml", UriKind.Relative);

일반적인 Pack URI 시나리오

이전 섹션에서는 리소스, 콘텐츠 및 원본 사이트 파일을 식별하는 Pack URI를 구성하는 방법에 대해 설명했습니다. WPF에서 이러한 생성은 다양한 방식으로 사용되며 다음 섹션에서는 몇 가지 일반적인 사용법에 대해 설명합니다.

애플리케이션을 시작할 때 표시되는 UI 지정

StartupUri는 WPF 애플리케이션이 시작될 때 표시할 첫 번째 UI를 지정합니다. 다음 예제와 같이 독립 실행형 애플리케이션의 경우 UI는 창이 될 수 있습니다.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

다음 예제와 같이 독립 실행형 애플리케이션과 XBAP(XAML 브라우저 애플리케이션)도 페이지를 초기 UI로 지정할 수 있습니다.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml" />

애플리케이션이 독립 실행형 애플리케이션이고 StartupUri를 사용하여 페이지를 지정한 경우 WPF는 페이지를 호스트하는 NavigationWindow를 엽니다. XBAP의 경우 호스트 브라우저에 페이지가 표시됩니다.

다음 예제에서는 페이지를 탐색하는 방법을 보여 줍니다.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page With Hyperlink"
  WindowWidth="250"
  WindowHeight="250">
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
  Navigate to Another Page
</Hyperlink>
</Page>

WPF에서 사용할 수 있는 다양한 탐색 방법에 대한 자세한 내용은 탐색 개요를 참조하세요.

창 아이콘 지정

다음 예제에서는 URI를 사용하여 창 아이콘을 지정하는 방법을 보여 줍니다.

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.MainWindow"
    Icon="WPFIcon1.ico">
</Window>

자세한 내용은 Icon를 참조하세요.

이미지, 오디오 및 비디오 파일 로드

다음 예제와 같이 WPF를 사용하면 애플리케이션에서 다양한 미디어 형식을 사용할 수 있습니다. 이러한 모든 미디어 형식은 Pack URI로 식별하고 로드할 수 있습니다.

<MediaElement Stretch="Fill" LoadedBehavior="Play" Source="pack://siteoforigin:,,,/Media/bee.wmv" />
<MediaElement Stretch="Fill" LoadedBehavior="Play" Source="pack://siteoforigin:,,,/Media/ringin.wav" />
<Image Source="Images/Watermark.png" />

미디어 콘텐츠 작업에 대한 자세한 내용은 그래픽 및 멀티미디어를 참조하세요.

원본 사이트에서 리소스 사전 로드

리소스 사전(ResourceDictionary)을 사용하면 애플리케이션 테마를 지원할 수 있습니다. 테마를 만들고 관리하는 한 가지 방법은 애플리케이션의 원본 사이트에 위치한 리소스 사전으로 여러 개의 테마를 만드는 것입니다. 이렇게 하면 애플리케이션을 다시 컴파일하여 배포할 필요 없이 테마를 추가하고 업데이트할 수 있습니다. 다음 예제에서 볼 수 있는 것처럼 Pack URI를 사용하여 이러한 리소스 사전을 식별하고 로드할 수 있습니다.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml">
  <Application.Resources>
    <ResourceDictionary Source="pack://siteoforigin:,,,/PageTheme.xaml" />
  </Application.Resources>
</Application>

WPF에서 테마에 대한 개요를 보려면 스타일 지정 및 템플릿을 참조하세요.

참고 항목