XAML 및 사용자 지정 클래스
업데이트: 2007년 11월
XAML(Extensible Application Markup Language)은 모든 CLR(공용 언어 런타임) 언어로 사용자 지정 클래스 또는 구조체를 정의한 다음 WPF(Windows Presentation Foundation) 정의 XAML 태그와 사용자 지정 클래스의 XAML 태그를 동일한 태그 파일 내에서 함께 사용하는 것을 비롯하여 XAML 태그를 사용하여 해당 클래스에 액세스할 수 있도록 지원합니다. 이 항목에서는 사용자 지정 클래스를 XAML 요소로 사용하기 위한 요구 사항에 대해 설명합니다.
이 항목에는 다음 단원이 포함되어 있습니다.
- 응용 프로그램 또는 어셈블리의 사용자 지정 클래스
- 사용자 지정 클래스를 XAML 요소로 사용하기 위한 요구 사항
- 사용자 지정 클래스의 속성을 XAML 특성으로 사용하기 위한 요구 사항
- 사용자 지정 클래스의 이벤트에 XAML 이벤트 처리기 특성 구문을 사용하기 위한 요구 사항
- 컬렉션 속성 작성
- XAML 콘텐츠 속성 선언
- XAML Serialize
- 관련 항목
응용 프로그램 또는 어셈블리의 사용자 지정 클래스
XAML에서 사용하는 사용자 지정 클래스는 두 가지 방법으로 정의할 수 있습니다. 하나는 기본 WPF(Windows Presentation Foundation) 응용 프로그램을 생성하는 코드 숨김 코드 또는 다른 코드 내에 정의하는 것이고, 다른 하나는 클래스 라이브러리로 사용되는 DLL 또는 실행 파일과 같은 별도의 어셈블리에 클래스로 정의하는 것입니다. 각 방법마다 고유의 장단점이 있습니다.
클래스 라이브러리를 만드는 경우 사용자 지정 클래스를 서로 다른 여러 응용 프로그램에서 공유할 수 있다는 장점이 있습니다. 또한 별도의 라이브러리를 만들면 응용 프로그램의 버전 관리 문제를 보다 쉽게 제어하고 XAML 페이지에서 루트 요소로 사용할 클래스를 간편하게 만들 수 있습니다.
사용자 지정 클래스를 응용 프로그램에 정의하는 방법은 비교적 간단하며 기본 실행 파일이 아닌 별도의 어셈블리를 사용할 때 발생하는 배포 및 테스트 문제를 최소화할 수 있다는 장점이 있습니다. 하지만 동일한 어셈블리에 정의된 클래스는 XAML 페이지의 루트 요소로 사용할 수 없다는 한 가지 중요한 단점이 있습니다.
동일한 어셈블리에 정의되어 있는지 아니면 다른 어셈블리에 정의되어 있는지에 관계없이 사용자 지정 클래스를 XAML에서 요소로 사용하려면 CLR 네임스페이스와 XML 네임스페이스 간에 사용자 지정 클래스를 매핑해야 합니다. XAML 네임스페이스 및 네임스페이스 매핑을 참조하십시오.
사용자 지정 클래스를 XAML 요소로 사용하기 위한 요구 사항
클래스를 개체 요소로 인스턴스화하려면 클래스가 다음 요구 사항을 충족해야 합니다.
사용자 지정 클래스가 공용 클래스여야 하고 매개 변수가 없는 기본 공용 생성자를 지원해야 합니다. 관리 코드 구조에서는 이러한 생성자를 암시적으로 지원합니다.
사용자 지정 클래스가 중첩 클래스가 아니어야 합니다. 중첩 클래스 및 클래스 구문의 "점"은 연결된 속성과 같은 WPF의 다른 기능을 방해합니다.
개체 요소 구문을 사용하는 것 외에도 해당 개체를 값 형식으로 사용하는 다른 공용 속성에 대해서는 속성 요소 구문을 사용해야 합니다. 그 이유는 이제 개체가 개체 요소로 인스턴스화되어 이러한 속성의 속성 요소 값을 채울 수 있기 때문입니다.
구조체
CLR 컴파일러는 구조체에 모든 속성 값을 기본값으로 초기화하는 기본 생성자를 암시적으로 만들기 때문에 사용자 지정 형식으로 정의하는 구조체를 항상 WPF에서 XAML로 생성할 수 있습니다. 그러나 경우에 따라서는 구조체의 기본 생성 동작 및/또는 개체 요소를 사용하지 않는 것이 바람직할 수 있습니다. 포함된 값의 해석이 서로 달라서 어느 속성도 설정할 수 없는 경우에 구조체가 값을 채우고 개념적으로 공용 구조체로 사용되어야 하는 경우가 여기에 해당합니다. 이러한 구조체의 WPF 예로 GridLength를 들 수 있습니다. 일반적으로 이러한 구조체는 값을 특성 형식으로 표현할 수 있도록 형식 변환기를 구현해야 하며 구조체의 값에 대해 서로 다른 해석이나 모드를 만드는 문자열 규칙을 사용해야 합니다. 또한 이러한 구조체는 기본값이 아닌 생성자를 통해 코드를 생성하는 경우에도 이와 유사한 동작을 노출해야 합니다.
사용자 지정 클래스의 속성을 XAML 특성으로 사용하기 위한 요구 사항
속성이 값 기준 형식(예: 기본 형식)을 참조하거나 클래스 수준에서 기본 생성자나 전용 형식 변환기를 가지고 있는 형식에 대한 클래스를 사용해야 합니다.
또는 속성이 추상 클래스 형식 또는 인터페이스를 참조할 수도 있습니다. 추상 클래스나 인터페이스의 경우 런타임에 해당 인터페이스를 구현하는 실제 클래스 인스턴스로 또는 추상 클래스에서 파생되는 클래스 인스턴스로 속성 값이 채워집니다.
클래스에 대한 개체 요소를 만들려면 클래스에 공용의 기본 생성자가 필요하기 때문에 속성을 추상 클래스에 선언할 수는 있지만 속성을 설정하는 것은 추상 클래스에서 파생되는 실제 클래스에서만 가능합니다.
형식 변환기를 통한 특성 구문 사용
클래스 수준에서 전용 특성 사용 형식 변환기를 제공한 경우 적용된 형식 변환을 사용하면 해당 형식을 인스턴스화해야 하는 모든 속성에 특성 구문을 사용할 수 있습니다. 형식 변환기는 해당 형식의 개체 요소를 사용하지 않습니다. 해당 형식에 대한 기본 생성자가 있는 경우에만 개체 요소를 사용할 수 있습니다. 따라서 형식 변환기가 사용하는 속성은 일반적으로 속성 구문에서 사용할 수 없습니다. 단, 형식 자체가 개체 요소 구문도 지원하는 경우는 예외입니다. 한 가지 예외적인 경우로 속성 요소에 문자열을 포함하여 속성 요소 구문을 지정할 수 있습니다. 이는 기본적으로 특성 구문을 사용하는 것과 같지만, 특성 값에 대한 보다 강력한 공백 처리가 필요한 경우가 아니면 일반적이지 않은 방법입니다. 예를 들어 다음은 문자열을 사용하는 속성 요소를 사용하는 방법을 보여 주며 이는 특성을 사용하는 것과 같습니다.
<Button>Hallo!
<Button.Language>
de-DE
</Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>
XAML에서 특성 구문은 허용되지만 개체 요소가 포함된 속성 요소 구문은 허용되지 않는 속성의 예로는 Cursor 형식을 사용하는 여러 속성이 있습니다. Cursor 클래스에는 전용 형식 변환기인 CursorConverter가 있지만 기본 생성자를 노출하지 않으므로 Cursor 속성은 실제 Cursor 형식이 참조 형식인 경우에도 특성 구문을 통해서만 설정할 수 있습니다.
속성별 형식 변환기
속성 자체가 속성 수준에서 형식 변환기를 선언할 수도 있습니다. 이렇게 하면 특성의 들어오는 문자열 값을 해당 형식에 따라 ConvertFrom 작업의 입력으로 처리하여, 속성 형식의 개체를 인라인으로 인스턴스화하는 "미니 언어"를 사용할 수 있습니다. 일반적으로 이 방법은 XAML에서 속성을 설정하기 위한 유일한 방법이 아니라 편리한 접근자를 제공하기 위해 사용합니다. 그러나 기본 생성자나 특성 사용 형식 변환기를 제공하지 않는 기존 CLR 형식을 사용하려는 특성에 대해 형식 변환기를 사용할 수도 있습니다. WPF API에서는 CultureInfo 형식을 사용하는 몇몇 속성을 예로 들 수 있습니다. 이 경우 WPF는 이전 버전 프레임워크에 사용된 호환성 및 마이그레이션 시나리오 문제를 해결하기 위해 기존 Microsoft .NET Framework CultureInfo 형식을 사용했습니다. 하지만 CultureInfo 형식은 필요한 생성자나 형식 수준 형식 변환을 XAML 속성 값으로 직접 사용하는 것을 지원하지 않았습니다.
따라서 컨트롤 작성자는 XAML을 사용하는 속성을 노출할 때마다 해당 속성에 종속성 속성을 지원하는 방법을 고려해야 합니다. DependencyProperty 지원을 사용하면 성능을 향상시킬 수 있으므로 이 방법은 특히 XAML 프로세서의 기존 WPF(Windows Presentation Foundation) 구현을 사용하는 경우 필요합니다. 종속성 속성은 애니메이션, 데이터 바인딩, 스타일 지원 등 XAML 액세스 가능 속성이 제공할 것으로 예상되는 속성 시스템의 기능을 제공합니다. 자세한 내용은 사용자 지정 종속성 속성 및 XAML 로드 및 종속성 속성을 참조하십시오.
형식 변환기 작성 및 특성 설정
속성 형식에 형식 변환을 제공하기 위해 사용자 지정 TypeConverter 파생 클래스를 작성해야 하는 경우가 있습니다. 형식 변환기에서 파생하여 XAML 사용을 지원하는 형식 변환기를 만드는 방법 및 TypeConverterAttribute를 적용하는 방법은 TypeConverter 및 XAML을 참조하십시오.
사용자 지정 클래스의 이벤트에 XAML 이벤트 처리기 특성 구문을 사용하기 위한 요구 사항
CLR 이벤트로 사용할 이벤트는 파생 클래스에서의 이벤트 액세스가 가능한 추상 클래스 또는 기본 생성자를 지원하는 클래스에 공용 이벤트로 노출되어야 합니다. 이벤트를 간편하게 라우트된 이벤트로 사용하려면 CLR 이벤트가 명시적 add 및 remove 메서드를 구현해야 합니다. 이 두 메서드는 CLR 이벤트 시그니처에 대한 처리기를 추가 및 제거하며 이러한 처리기를 AddHandler 및 RemoveHandler 메서드에 전달합니다. 이 두 메서드는 이벤트가 연결된 인스턴스의 라우트된 이벤트 처리기 저장소에 처리기를 추가하거나 제거합니다.
참고
AddHandler를 사용하여 라우트된 이벤트에 대한 처리기를 직접 등록할 수 있습니다. 또한 라우트된 이벤트를 노출하는 CLR 이벤트를 의도적으로 정의하지 않을 수도 있습니다. 이 경우 이벤트가 처리기를 연결할 때 XAML 특성 구문을 사용하지 않게 되고 결과적으로 생성된 클래스는 클래스 개체 모델에 대한 완벽하지 않은 XAML 뷰를 제공하게 되므로 일반적으로 권장되지 않는 방법입니다.
컬렉션 속성 작성
컬렉션 형식을 사용하는 속성에는 컬렉션에 추가할 개체를 지정하는 데 사용할 수 있는 XAML 구문이 있습니다. 이 구문은 다음과 같은 두 가지 중요한 기능을 제공합니다.
개체(컬렉션 개체)를 개체 요소 구문에 지정할 필요가 없습니다. 컬렉션 형식을 사용하는 XAML에 속성을 지정하는 경우 컬렉션 형식이 항상 암시적으로 존재합니다.
컬렉션 속성의 자식 요소가 컬렉션의 멤버로 처리됩니다. 일반적으로 컬렉션 멤버에 대한 코드 액세스는 Add와 같은 컬렉션 메서드를 통해 또는 컬렉션 인덱서 속성을 통해 수행됩니다. 하지만 XAML 구문은 메서드나 인덱서를 지원하지 않습니다. 컬렉션은 요소 트리를 구성하는 데 있어 공통된 요구 사항이므로 선언적 XAML에서 이러한 컬렉션을 채우는 데 사용할 몇 가지 방법이 필요합니다. 따라서 컬렉션 속성의 자식 요소는 컬렉션 속성 형식 값에 해당하는 컬렉션에 추가됩니다.
WPF XAML 프로세서는 컬렉션 속성을 구성하는 항목에 대해 다음 정의를 사용합니다. 속성의 속성 형식은 다음 중 하나를 구현해야 합니다.
IList 구현
IDictionary 또는 해당 제네릭(IDictionary<TKey, TValue>) 구현
Array에서 파생(XAML에서의 배열에 대한 자세한 내용은 x:Array 태그 확장 참조)
IAddChild(WPF에 정의된 인터페이스) 구현
이러한 각 형식에는 XAML 프로세서가 기본 컬렉션에 항목을 추가하는 데 사용하는 Add 메서드가 있습니다.
참고
WPF XAML 프로세서를 통한 컬렉션 검색에는 제네릭 List 및 Dictionary 인터페이스(IList<T> 및 IDictionary<TKey, TValue>)가 지원되지 않습니다. 하지만 List<T> 클래스는 IList를 직접 구현하므로 이를 기본 클래스로 사용할 수 있습니다. 또는 Dictionary<TKey, TValue> 클래스는 IDictionary를 직접 구현하므로 이를 기본 클래스로 사용할 수도 있습니다.
컬렉션을 사용하는 속성을 선언하는 경우 해당 형식의 새 인스턴스에서 속성 값이 초기화되는 방법에 유의하십시오. 속성을 종속성 속성으로 구현하지 않는 경우에는 속성이 컬렉션 형식 생성자를 호출하는 지원 필드를 사용하도록 설정하는 것이 좋습니다. 속성이 종속성 속성인 경우에는 기본 형식 생성자의 일부로 컬렉션 속성을 초기화해야 할 수 있습니다. 그 이유는 종속성 속성이 속성의 기본값을 메타데이터에서 가져오는데, 개발자는 컬렉션 속성의 초기 값을 정적 공유 컬렉션(각각의 포함하는 형식 인스턴스마다 컬렉션 인스턴스가 있어야 함)에 사용하지 않으려는 것이 일반적이기 때문입니다. 자세한 내용은 사용자 지정 종속성 속성을 참조하십시오.
컬렉션 속성에 대해 사용자 지정 컬렉션 형식을 구현할 수 있습니다. 암시적 컬렉션 속성 처리로 인해 사용자 지정 컬렉션 형식은 기본 생성자를 제공하지 않아도 XAML에서 암시적으로 사용할 수 있습니다. 하지만 필요한 경우 컬렉션 형식에 대한 기본 생성자를 제공할 수도 있습니다. 기본 생성자를 제공하지 않으면 컬렉션을 개체 요소로 명시적으로 선언할 수 없으므로 기본 생성자를 제공하는 것이 좋습니다. 명시적 컬렉션을 태그 스타일의 문제로 보는 태그 작성자도 있습니다. 기본 생성자를 사용하면 컬렉션 형식을 속성 값으로 사용하는 새 개체를 만들 때 초기화 요구 사항을 줄일 수도 있습니다.
XAML 콘텐츠 속성 선언
XAML 언어는 XAML 콘텐츠 속성이라는 개념을 정의합니다. 개체 구문에서 사용할 수 있는 각 클래스는 정확히 하나의 XAML 콘텐츠 속성을 포함할 수 있습니다. 속성을 클래스의 XAML 콘텐츠 속성으로 선언하려면 클래스 정의의 일부로 ContentPropertyAttribute를 적용합니다. 특성에서 Name으로 선언할 XAML 콘텐츠 속성의 이름을 지정합니다.
컬렉션 속성을 XAML 콘텐츠 속성으로 지정할 수 있습니다. 이 경우 중간의 컬렉션 개체 요소나 속성 요소 태그 없이도 개체 요소가 하나 이상의 자식 요소를 가질 수 있는 상황에서 해당 속성이 사용됩니다. 그러면 이러한 요소가 XAML 콘텐츠 속성에 대한 값으로 처리되어 지원 컬렉션 인스턴스에 추가됩니다.
일부 기존 WPF XAML 콘텐츠 속성은 Object 속성 형식을 사용합니다. 이 때문에 XAML 콘텐츠 속성은 String과 같은 기본값뿐만 아니라 단일 참조 개체 값을 사용할 수 있습니다. 이 모델을 따르는 경우 사용자의 형식을 통해 형식을 결정하고 가능한 형식을 처리합니다. Object 형식 모델에서 이와 같이 하는 이유는 개체 콘텐츠를 문자열(기본 표현 처리를 수신)로 추가하는 단순한 방법과 기본이 아닌 표현을 지정하는 개체 콘텐츠를 추가하는 고급 방법을 모두 지원하기 위해서입니다.
XAML Serialize
컨트롤 작성자가 XAML로 인스턴스화할 수 있는 모든 개체 표현을 다시 해당 XAML로 serialize하려는 특정한 시나리오도 있습니다. 이 항목에서는 serialization 요구 사항에 대해서는 설명하지 않습니다. 컨트롤 제작 개요 및 요소 트리 및 serialization을 참조하십시오.