XAML 구문 정보

이 토픽에서는 XAML 구문 요소를 설명하는 데 사용되는 용어를 정의합니다. 이러한 용어는 이 설명서의 나머지 부분, 특히 WPF 설명서와 XAML을 사용하는 다른 프레임워크 또는 System.Xaml 수준에서 XAML 언어 지원을 통해 지원되는 기본 XAML 개념에 대해 설명하는 데 자주 사용됩니다. 이 토픽에서는 WPF의 XAML 토픽에 도입된 기본 용어를 확장합니다.

XAML 언어 사양

여기에 정의된 XAML 구문 용어는 XAML 언어 사양 내에서도 정의되거나 참조됩니다. XAML은 XML 기반의 언어이며 XML 구조 규칙을 따르거나 확장합니다. 일부 용어는 XML 언어 또는 XML 문서 개체 모델을 설명할 때 일반적으로 사용되는 용어를 공유하거나 기반으로 합니다.

XAML 언어 사양에 대한 자세한 내용을 보려면 Microsoft 다운로드 센터에서 [MS-XAML]을 다운로드하세요.

XAML 및 CLR

XAML은 태그 언어입니다. CLR(공용 언어 런타임)은 이름에서 알 수 있듯이 런타임 실행을 가능하게 합니다. XAML은 그 자체로는 CLR 런타임에서 직접 사용하는 공용 언어가 아닙니다. 대신 XAML은 자체 형식 시스템을 지원한다고 생각하면 됩니다. WPF에서 사용하는 XAML 구문 분석 시스템은 CLR 및 CLR 형식 시스템을 기반으로 합니다. XAML 형식은 WPF용 XAML을 구문 분석할 때 런타임 표현을 인스턴스화하기 위해 CLR 형식에 매핑됩니다. 이러한 이유로 이 문서의 나머지 구문 설명에는 CLR 형식 시스템에 대한 참조가 포함되지만, XAML 언어 사양의 동등한 구문 설명에는 이 내용이 없습니다. (XAML 언어 사양 수준에 따라 XAML 형식은 다른 형식 시스템에 매핑할 수 있습니다. 다른 형식 시스템은 반드시 CLR일 필요는 없지만 다른 XAML 파서를 만들고 사용해야 합니다.)

형식 멤버 및 클래스 상속

WPF 형식의 XAML 멤버로 표시되는 속성과 이벤트는 기본 형식에서 상속되는 경우가 많습니다. <Button Background="Blue" .../> 예제를 생각해 보세요. 클래스 정의, 리플렉션 결과 또는 설명서를 살펴본다면 Background 속성은 Button 클래스에서 즉시 선언되는 속성이 아닙니다. 대신 Background는 기본 Control 클래스에서 상속됩니다.

WPF XAML 요소의 클래스 상속 동작은 XML 태그의 스키마 적용 해석에서 크게 벗어납니다. 클래스 상속은 특히 중간 기본 클래스가 추상이거나 인터페이스가 관련된 경우 복잡해질 수 있습니다. 이는 XAML 요소 세트와 해당 허용 특성이 DTD 또는 XSD 형식과 같은 XML 프로그래밍에 일반적으로 사용되는 스키마 형식을 정확하고 완전히 표현하기 어려운 이유 중 하나입니다. 또 다른 이유는 XAML 언어 자체의 확장성 및 형식 매핑 기능이 허용되는 형식 및 멤버의 고정된 표현의 완전성을 배제하기 때문입니다.

개체 요소 구문

개체 요소 구문은 XML 요소를 선언하여 CLR 클래스 또는 구조를 인스턴스화하는 XAML 태그 구문입니다. 이 구문은 HTML과 같은 다른 태그 언어의 요소 구문과 유사합니다. 개체 요소 구문은 왼쪽 꺾쇠 괄호(<)로 시작하고, 바로 뒤에 인스턴스화되는 클래스 또는 구조체의 형식 이름이 옵니다. 형식 이름 뒤에는 0개 이상의 공백이 올 수 있고, 개체 요소에서 0개 이상의 특성을 선언할 수도 있으며, 하나 이상의 공백이 각 특성 이름="값" 쌍을 구분합니다. 마지막으로, 다음 중 하나가 참이어야 합니다.

  • 요소와 태그를 슬래시(/)로 닫고, 바로 뒤에서 오른쪽 꺾쇠괄호(>)로 닫아야 합니다.

  • 여는 태그는 오른쪽 꺾쇠 괄호(>)로 완료해야 합니다. 다른 개체 요소, 속성 요소 또는 내부 텍스트는 여는 태그 뒤에 올 수 있습니다. 여기에 포함될 수 있는 콘텐츠는 일반적으로 요소의 개체 모델에 의해 제한됩니다. 개체 요소에 해당하는 닫는 태그도 있어야 하며, 이 태그는 다른 여는 태그 및 닫는 태그 쌍과 적절하게 중첩되고 균형을 유지해야 합니다.

.NET으로 구현된 XAML에는 개체 요소를 형식에, 특성을 속성 또는 이벤트에, XAML 네임스페이스를 CLR 네임스페이스와 어셈블리에 매핑하는 규칙 세트가 있습니다. WPF 및 .NET의 경우 XAML 개체 요소는 참조된 어셈블리에 정의된 대로 .NET 형식에 매핑되고, 특성은 해당 형식의 멤버에 매핑됩니다. XAML에서 CLR 형식을 참조하는 경우 해당 형식의 상속된 멤버에도 액세스할 수 있습니다.

예를 들어 다음 예제는 Button 클래스의 새 인스턴스를 인스턴스화하고 Name 특성과 이 특성의 값을 지정하는 개체 요소 구문입니다.

<Button Name="CheckoutButton"/>

다음 예제는 XAML 콘텐츠 속성 구문도 포함하는 개체 요소 구문입니다. 내부에 포함된 내부 텍스트는 TextBox XAML 콘텐츠 속성인 Text를 설정하는 데 사용됩니다.

<TextBox>This is a Text Box</TextBox>

콘텐츠 모델

클래스는 구문 측면에서 XAML 개체 요소로 사용할 수 있지만, 해당 요소는 전체 콘텐츠 모델 또는 요소 트리의 예상 위치에 배치될 때만 애플리케이션 또는 페이지에서 제대로 작동합니다. 예를 들어 MenuItem은 일반적으로 MenuBase 파생 클래스의 자식으로만 배치해야 합니다(예: Menu). 특정 요소에 대한 콘텐츠 모델은 컨트롤의 클래스 페이지 및 XAML 요소로 사용할 수 있는 다른 WPF 클래스에 대한 설명의 일부로 설명됩니다.

개체 요소의 속성

XAML의 속성은 가능한 다양한 구문에 의해 설정됩니다. 특정 속성에 사용할 수 있는 구문은 설정하는 속성의 기본 형식 시스템 특성에 따라 달라집니다.

속성 값을 설정하여 런타임 개체 그래프에 존재하는 특성 또는 특성을 개체에 추가합니다. 개체 요소에서 만들어진 개체의 초기 상태는 매개 변수가 없는 생성자 동작을 기반으로 합니다. 일반적으로 애플리케이션은 특정 개체의 완전 기본 인스턴스가 아닌 다른 항목을 사용합니다.

특성 구문(속성)

특성 구문은 기존 개체 요소의 특성을 선언하여 속성의 값을 설정하는 XAML 태그 구문입니다. 특성 이름은 관련 개체 요소를 백업하는 클래스 속성의 CLR 멤버 이름과 일치해야 합니다. 특성 이름 뒤에는 대입 연산자(=)가 옵니다. 특성 값은 따옴표로 묶인 문자열이어야 합니다.

참고

따옴표를 번갈아 사용하여 특성 내에 리터럴 따옴표를 배치할 수 있습니다. 예를 들어 작은따옴표를 사용하여 안에 큰따옴표 문자가 포함된 문자열을 선언할 수 있습니다. 작은따옴표를 사용하든 큰따옴표를 사용하든, 일치하는 쌍을 특성 값 문자열을 열고 닫는 데 사용해야 합니다. 특정 XAML 구문에 의해 적용되는 문자 제한을 해결하는 데 사용할 수 있는 이스케이프 시퀀스 또는 기타 기술도 있습니다. XML 문자 엔터티 및 XAML을 참조하세요.

특성 구문을 통해 설정하려면 속성이 public이어야 하고 쓸 수 있어야 합니다. 지원 형식 시스템의 속성 값은 값 형식이거나, 관련 지원 형식에 액세스할 때 XAML 프로세서에서 인스턴스화하거나 참조할 수 있는 참조 형식이어야 합니다.

WPF XAML 이벤트의 경우 특성 이름으로 참조되는 이벤트는 public이어야 하며 공용 대리자가 있어야 합니다.

속성 또는 이벤트는 포함하는 개체 요소에 의해 인스턴스화된 클래스 또는 구조체의 멤버여야 합니다.

특성 값 처리

여는 따옴표와 닫는 따옴표 안에 포함된 문자열 값은 XAML 프로세서에서 처리됩니다. 속성의 경우 기본 처리 동작은 기본 CLR 속성의 형식에 따라 결정됩니다.

특성 값은 이 처리 순서를 사용하여 다음 중 하나로 채워집니다.

  1. XAML 프로세서에서 중괄호 또는 MarkupExtension에서 파생되는 개체 요소가 발견되면 값을 문자열로 처리하는 대신 참조된 태그 확장이 먼저 평가되고, 태그 확장에서 반환된 개체가 값으로 사용됩니다. 대부분의 경우 태그 확장에서 반환된 개체는 기존 개체의 참조이거나, 런타임까지 평가를 지연하며 새로 인스턴스화된 개체가 아닌 식입니다.

  2. 속성이 TypeConverter 특성으로 선언되거나, 해당 속성의 값 형식이 TypeConverter 특성으로 선언되면 특성의 문자열 값이 형식 변환기에 변환 입력으로 제출되고 변환기는 새 개체 인스턴스를 반환합니다.

  3. TypeConverter가 없는 경우 속성 형식으로 직접 변환을 시도합니다. 이 최종 수준은 XAML 언어 기본 형식 간의 파서 네이티브 값에서 직접 변환하거나, 열거형에서 명명된 상수의 이름을 검사하는 것입니다(그러면 파서는 일치하는 값에 액세스함).

열거형 특성 값

XAML의 열거형은 본질적으로 XAML 파서에서 처리되며, 열거형의 멤버는 열거형의 명명된 상수 중 하나의 문자열 이름을 지정하여 지정해야 합니다.

비플래그 열거형 값의 경우 네이티브 동작은 특성 값의 문자열을 처리하고 열거형 값 중 하나로 확인하는 것입니다. 코드에서 하듯이 열거형. 형식으로 열거형을 지정하지 않습니다. 대신 만 지정하고, 열거형은 설정하는 속성의 형식으로 유추됩니다. 열거형. 형식으로 특성을 지정하면 올바르게 확인되지 않습니다.

플래그 지정 열거형의 경우 동작은 Enum.Parse 메서드를 기반으로 합니다. 각 값을 쉼표로 구분하여 플래그 지정 열거형의 여러 값을 지정할 수 있습니다. 그러나 플래그 지정이 아닌 열거형 값은 결합할 수 없습니다. 예를 들어 쉼표 구문을 사용하여 비 플래그 열거형의 여러 조건에서 작동하는 Trigger를 만들 수 없습니다.

<!--This will not compile, because Visibility is not a flagwise enumeration.-->  
...  
<Trigger Property="Visibility" Value="Collapsed,Hidden">  
  <Setter ... />  
</Trigger>  
...  

XAML에서 설정할 수 있는 특성을 지원하는 플래그 지정 열거형은 WPF에서 드뭅니다. 그러나 이러한 열거형은 StyleSimulations입니다. 예를 들어 쉼표로 구분된 플래그 지정 특성 구문을 사용하여 Glyphs 클래스에 대한 설명에 제공된 예제를 수정할 수 있습니다. StyleSimulations = "BoldSimulation"StyleSimulations = "BoldSimulation,ItalicSimulation"이 될 수 있습니다. KeyBinding.Modifiers는 둘 이상의 열거형 값을 지정할 수 있는 또 다른 속성입니다. 그러나 ModifierKeys 열거형이 자체 형식 변환기를 지원하므로 이 속성은 특별한 사례입니다. 한정자의 형식 변환기는 쉼표(,)가 아닌 더하기 기호(+)를 구분 기호로 사용합니다. 이 변환은 "Ctrl+Alt"와 같은 Microsoft Windows 프로그래밍의 키 조합을 나타내는 기존 구문을 지원합니다.

속성 및 이벤트 멤버 이름 참조

특성을 지정할 때, 포함하는 개체 요소에 대해 인스턴스화한 CLR 형식의 멤버로 존재하는 속성 또는 이벤트를 참조할 수 있습니다.

또는 포함하는 개체 요소와 상관없이, 연결된 속성 또는 연결된 이벤트를 참조할 수 있습니다. (연결된 속성은 향후 섹션에서 설명합니다.)

typeName.event 부분적으로 정규화된 이름을 사용하여 기본 네임스페이스를 통해 액세스할 수 있는 개체의 이벤트 이름을 지정할 수도 있습니다. 이 구문은 처리기가 자식 요소의 이벤트 라우팅을 처리하는 데 사용되는 라우트된 이벤트에 대한 처리기 연결을 지원하지만, 부모 요소에는 해당 멤버 테이블에 해당 이벤트가 없습니다. 이 구문은 연결된 이벤트 구문과 유사하지만, 여기에 있는 이벤트는 실제 연결된 이벤트가 아닙니다. 대신 정규화된 이름을 사용하는 이벤트를 참조합니다. 자세한 내용은 라우트된 이벤트 개요를 참조하세요.

일부 시나리오에서는 속성 이름이 특성 이름이 아닌 특성 값으로 제공되는 경우도 있습니다. 해당 속성 이름에는 ownerType.dependencyPropertyName 형식으로 지정된 속성과 같은 한정자가 포함될 수도 있습니다. 이 시나리오는 XAML에서 스타일 또는 템플릿을 작성할 때 일반적입니다. 특성 값으로 제공되는 속성 이름의 처리 규칙은 다르며, 설정되는 속성의 형식 또는 특정 WPF 하위 시스템의 동작에 의해 제어됩니다. 자세한 내용은 스타일 지정 및 템플릿을 참조하세요.

속성 이름에 대한 또 다른 사용법은 특성 값이 속성-속성 관계를 설명하는 경우입니다. 이 기능은 데이터 바인딩 및 스토리보드 대상에 사용되며. PropertyPath 클래스 및 해당 형식 변환기에서 사용됩니다. 조회 의미 체계에 대한 자세한 설명은 PropertyPath XAML 구문을 참조하세요.

속성 요소 구문

속성 요소 구문은 요소에 대한 기본 XML 구문 규칙과 다소 다른 구문입니다. XML에서는 특성 값이 사실상 문자열이며, 유일하게 가능한 변형은 사용되는 문자열 인코딩 형식입니다. XAML에서는 다른 개체 요소를 속성 값으로 할당할 수 있습니다. 이 기능은 속성 요소 구문에 의해 활성화됩니다. 속성이 요소 태그 내에서 특성으로 지정되는 대신, elementTypeName.propertyName 형식의 여는 요소 태그를 사용하여 속성이 지정되고 그 안에서 속성 값이 지정된 다음, 속성 요소가 닫힙니다.

구체적으로 말하면, 구문은 왼쪽 꺾쇠 괄호(<)로 시작하고, 바로 뒤에 속성 요소 구문이 포함된 클래스 또는 구조체의 형식 이름이 옵니다. 형식 이름의 바로 뒤에는 점 하나(.), 속성 이름, 오른쪽 꺾쇠괄호(>)가 차례로 옵니다. 특성 구문과 마찬가지로 해당 속성은 지정된 형식의 선언된 공용 멤버 내에 있어야 합니다. 속성에 할당할 값은 속성 요소 내에 포함됩니다. 일반적으로 개체를 값으로 지정하는 것은 속성 요소 구문을 해결하기 위한 시나리오이기 때문에 값은 하나 이상의 개체 요소로 제공됩니다. 마지막으로, 동일한 elementTypeName.propertyName 조합을 지정하는 동등한 닫는 태그를 입력해야 하며, 이 태그는 다른 요소 태그와 적절하게 중첩되고 균형을 유지해야 합니다.

예를 들어 다음은 ButtonContextMenu 속성에 대한 속성 요소 구문입니다.

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

지정되는 속성 형식이 기본 값 형식(예: String) 또는 이름이 지정된 열거형인 경우 속성 요소 내의 값을 내부 텍스트로 지정할 수도 있습니다. 이러한 두 가지 사용법은 다소 일반적이지 않습니다. 각각의 경우에 보다 간단한 특성 구문을 사용할 수도 있기 때문입니다. 속성 요소를 문자열로 채우는 한 가지 시나리오는 XAML 콘텐츠 속성은 아니지만 여전히 UI 텍스트의 표현에 사용되는 속성이며, 해당 UI 텍스트에 줄 바꿈과 같은 특정 공백 요소가 나타나야 하는 경우입니다. 특성 구문은 줄 바꿈을 유지할 수 없지만, 속성 요소 구문은 유효 공백 보존이 활성 상태인 한 줄 바꿈을 유지할 수 있습니다(자세한 내용은 XAML의 공백 처리 참조). 또 다른 시나리오는 x:Uid 지시문을 속성 요소에 적용하여 값을 WPF 출력 BAML 또는 다른 기술에서 지역화해야 하는 값으로 표시하는 것입니다.

속성 요소는 WPF 논리 트리에 표시되지 않습니다. 속성 요소는 속성을 설정하기 위한 특정 구문일 뿐이며, 속성을 지원하는 인스턴스 또는 개체를 갖고 있는 요소가 아닙니다. (논리 트리 개념에 대한 자세한 내용은 WPF의 트리를 참조하세요.)

특성 및 속성 요소 구문이 모두 지원되는 속성의 경우 일반적으로 두 구문의 결과는 동일하지만, 공백 처리와 같은 미묘한 특성은 구문마다 약간 다를 수 있습니다.

컬렉션 구문

XAML 사양은 값 형식이 컬렉션인 속성을 식별하는 XAML 프로세서 구현을 요구합니다. .NET의 일반적인 XAML 프로세서 구현은 관리 코드 및 CLR을 기반으로 하며, 다음 중 한 가지 방법을 통해 컬렉션 형식을 식별합니다.

속성의 형식이 컬렉션인 경우 유추된 컬렉션 형식을 태그에서 개체 요소로 지정할 필요가 없습니다. 대신 컬렉션의 항목이 되도록 의도된 요소는 속성 요소의 하나 이상의 자식 요소로 지정됩니다. 이러한 각 항목은 로드하는 동안 개체에 평가되고 암시적 컬렉션의 Add 메서드를 호출하여 컬렉션에 추가됩니다. 예를 들어 속성 StyleTriggers 속성은 IList를 구현하는 특수 컬렉션 형식 TriggerCollection을 사용합니다. 태그에서 TriggerCollection 개체 요소를 인스턴스화할 필요는 없습니다. 대신 하나 이상의 Trigger 항목을 Style.Triggers 속성 요소 내의 요소로 지정합니다. 여기서 Trigger(또는 파생 클래스)는 강력한 형식 및 암시적 TriggerCollection의 항목 형식으로 예상되는 형식입니다.

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

속성은 이 토픽의 다음 섹션에서 설명하는 해당 형식 및 파생 형식에 대한 컬렉션 형식 및 XAML 콘텐츠 속성일 수 있습니다.

암시적 컬렉션 요소는 태그에 요소로 표시되지 않더라도 논리 트리 표현에서 멤버를 만듭니다. 일반적으로 부모 형식의 생성자는 해당 속성 중 하나인 컬렉션을 인스턴스화하고, 처음에는 빈 컬렉션이 개체 트리의 일부가 됩니다.

참고

일반 목록 및 사전 인터페이스(IList<T>IDictionary<TKey,TValue>)는 컬렉션 탐지를 지원하지 않습니다. 그러나 IList를 직접 구현하는 List<T> 클래스를 기본 클래스로 사용하거나 IDictionary를 직접 구현하는 Dictionary<TKey,TValue>를 기본 클래스로 사용할 수 있습니다.

컬렉션 형식에 대한 .NET 참조 페이지에서, 컬렉션에 대한 개체 요소를 의도적으로 생략한 이 구문은 XAML 구문 섹션에서 암시적 컬렉션 구문으로 언급되기도 합니다.

루트 요소를 제외하고, 다른 요소의 자식 요소로 중첩된 XAML 파일의 모든 개체 요소는 실제로 부모 요소의 암시적 컬렉션 속성 멤버 또는 부모 요소에 대한 XAML 콘텐츠 속성의 값을 지정하는 요소이거나 둘 다입니다(XAML 콘텐츠 속성은 향후 섹션에서 설명). 즉, 태그 페이지에서 부모 요소와 자식 요소의 관계는 실제로는 루트의 단일 개체이며, 루트 아래의 모든 개체 요소는 부모의 속성 값을 제공하는 단일 인스턴스이거나 부모의 컬렉션 형식 속성 값이기도 한 컬렉션 내의 항목 중 하나입니다. 이 단일 루트 개념은 XML에서 일반적이며, Load처럼 XAML을 로드하는 API의 동작에서 자주 강화됩니다.

다음 예제는 명시적으로 지정된 컬렉션(GradientStopCollection)에 개체 요소를 사용하는 구문입니다.

<LinearGradientBrush>  
  <LinearGradientBrush.GradientStops>  
    <GradientStopCollection>  
      <GradientStop Offset="0.0" Color="Red" />  
      <GradientStop Offset="1.0" Color="Blue" />  
    </GradientStopCollection>  
  </LinearGradientBrush.GradientStops>  
</LinearGradientBrush>  

컬렉션을 항상 명시적으로 선언할 수 있는 것은 아닙니다. 예를 들어 앞에서 보여 드린 Triggers 예제에서 TriggerCollection을 명시적으로 선언하려고 하면 실패합니다. 컬렉션을 명시적으로 선언하려면 컬렉션 클래스가 매개 변수 없는 생성자를 지원해야 하고, TriggerCollection에는 매개 변수 없는 생성자가 없어야 합니다.

XAML 콘텐츠 속성

XAML 콘텐츠 구문은 클래스 선언의 일부로 ContentPropertyAttribute를 지정하는 클래스에서만 사용되는 구문입니다. ContentPropertyAttribute는 파생 클래스를 포함하여 해당 요소 형식의 콘텐츠 속성인 속성 이름을 참조합니다. XAML 프로세서에서 처리할 때, 개체 요소의 여는 태그와 닫는 태그 사이에 있는 자식 요소 또는 내부 텍스트는 해당 개체의 XAML 콘텐츠 속성 값으로 할당됩니다. 콘텐츠 속성의 명시적 속성 요소를 지정할 수 있지만, 이 사용법은 .NET 참조의 XAML 구문 섹션에서 일반적으로 보여주지 않습니다. 명시적/자세한 정보 표시 기술은 태그 선명도 또는 태그 스타일의 문제로 가끔 값을 가지지만, 일반적으로 콘텐츠 속성의 의도는 부모-자식으로 직관적으로 관련된 요소를 직접 중첩할 수 있도록 태그를 간소화하는 것입니다. 요소의 다른 속성에 대한 속성 요소 태그는 엄격한 XAML 언어 정의에 따라 "콘텐츠"로 할당되지 않습니다. 앞에서 XAML 파서의 처리 순서에 따라 처리되며 "콘텐츠"로 간주되지 않습니다.

XAML 콘텐츠 속성 값은 연속되어야 합니다.

XAML 콘텐츠 속성의 값은 해당 개체 요소의 다른 모든 속성 요소의 맨 앞 또는 맨 뒤에 지정해야 합니다. XAML 콘텐츠 속성의 값이 문자열로 지정되든 하나 이상의 개체로 지정되든, 이는 마찬가지입니다. 예를 들어 다음 태그는 구분 분석하지 않습니다.

<Button>I am a
  <Button.Background>Blue</Button.Background>  
  blue button</Button>  

콘텐츠 속성에 속성 요소 구문을 사용하여 이 구문을 명시적으로 지정한 경우 콘텐츠 속성이 두 번 설정되기 때문에 이는 기본적으로 불법입니다.

<Button>  
  <Button.Content>I am a </Button.Content>  
  <Button.Background>Blue</Button.Background>  
  <Button.Content> blue button</Button.Content>  
</Button>  

콘텐츠 속성이 컬렉션이고 자식 요소가 속성 요소와 섞여 있는 경우에도 마찬가지로 불법입니다.

<StackPanel>  
  <Button>This example</Button>  
  <StackPanel.Resources>  
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>  
  </StackPanel.Resources>  
  <Button>... is illegal XAML</Button>  
</StackPanel>  

콘텐츠 속성 및 컬렉션 구문 조합

둘 이상의 개체 요소를 콘텐츠로 수락하려면 콘텐츠 속성의 형식이 구체적으로 컬렉션 형식이어야 합니다. 컬렉션 형식의 속성 요소 구문과 마찬가지로 XAML 프로세서는 컬렉션 형식인 형식을 식별해야 합니다. 요소에 XAML 콘텐츠 속성이 있고 XAML 콘텐츠 속성의 형식이 컬렉션인 경우 암시적 컬렉션 형식을 태그에서 개체 요소로 지정할 필요가 없으며 XAML 콘텐츠 속성을 속성 요소로 지정할 필요가 없습니다. 따라서 태그의 명백한 콘텐츠 모델에는 이제 콘텐츠로 할당된 자식 요소가 2개 이상 있을 수 있습니다. 다음은 Panel 파생 클래스의 콘텐츠 구문입니다. 모든 Panel 파생 클래스는 XAML 콘텐츠 속성을 UIElementCollection 형식의 값이 필요한 Children으로 설정합니다.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Children에 대한 속성 요소와 UIElementCollection에 대한 요소는 태그에 필요하지 않습니다. 이는 UI를 정의하는 재귀적으로 포함된 요소가 속성 요소 태그 또는 컬렉션 개체의 개입 없이 즉각적인 부모-자식 요소 관계가 있는 중첩된 요소의 트리로 보다 직관적으로 표현되도록 하는 XAML의 디자인 기능입니다. 실제로 UIElementCollection은 태그에서 개체 요소로 명시적으로 지정할 수 없도록 설계되었습니다. 유일하게 의도된 용도는 암시적 컬렉션인 UIElementCollection이 공용 매개 변수 없는 생성자를 노출하지 않으므로 개체 요소로 인스턴스화할 수 없다는 것입니다.

콘텐츠 속성을 사용하여 속성 요소와 개체 요소를 개체에 혼합

XAML 사양은 XAML 프로세서가 개체 요소 내의 XAML 콘텐츠 속성을 채우는 데 사용되는 개체 요소가 연속적이어야 하며 혼합하면 안 되도록 적용할 수 있다고 선언합니다. 속성 요소와 콘텐츠 혼합에 대한 이러한 제한은 WPF XAML 프로세서에 의해 적용됩니다.

자식 개체 요소를 개체 요소 내의 첫 번째 직접 태그로 사용할 수 있습니다. 그런 다음, 속성 요소를 도입할 수 있습니다. 또는 하나 이상의 속성 요소를 지정하고 콘텐츠를 지정한 다음, 더 많은 속성 요소를 지정할 수 있습니다. 그러나 속성 요소가 콘텐츠를 따르면 추가 콘텐츠를 도입할 수 없고 속성 요소만 추가할 수 있습니다.

이 콘텐츠/속성 요소 순서 요구 사항은 콘텐츠로 사용되는 내부 텍스트에는 적용되지 않습니다. 그러나 속성 요소가 내부 텍스트와 섞여 있는 경우 태그에서 유효 공백을 시각적으로 감지하기 어렵기 때문에 내부 텍스트를 연속적으로 유지하는 것은 여전히 좋은 태그 스타일입니다.

XAML 네임스페이스

이전 구문 예제에서는 기본 XAML 네임스페이스 외에는 XAML 네임스페이스를 지정하지 않았습니다. 일반적인 WPF 애플리케이션에서 기본 XAML 네임스페이스는 WPF 네임스페이스로 지정됩니다. 기본 XAML 네임스페이스 외에도 XAML 네임스페이스를 지정하고 유사한 구문을 계속 사용할 수 있습니다. 그러나 기본 XAML 네임스페이스 내에서 액세스할 수 없는 클래스의 이름이 지정된 위치에서, 해당 클래스 이름 앞에는 해당 CLR 네임스페이스에 매핑된 XAML 네임스페이스의 접두사가 와야 합니다. 예를 들어 <custom:Example/>Example 클래스의 인스턴스를 인스턴스화하는 개체 요소 구문이며, 해당 클래스(및 가능한 경우 지원 형식이 포함된 외부 어셈블리 정보)를 포함하는 CLR 네임스페이스는 이전에 custom 접두사에 매핑되었습니다.

XAML 네임스페이스에 대한 자세한 내용은 WPF XAML을 위한 XAML 네임스페이스 및 네임스페이스 매핑을 참조하세요.

태그 확장

XAML은 문자열 특성 값 또는 개체 요소의 일반 XAML 프로세서 처리에서 이스케이프를 사용하도록 설정하고 처리를 지원 클래스로 연기할 수 있는 태그 확장 프로그래밍 엔터티를 정의합니다. 특성 구문을 사용할 때 XAML 프로세서에 대한 태그 확장을 식별하는 문자는 여는 중괄호({), 그리고 그 뒤에는 중괄호(}) 이외의 문자입니다. 여는 중괄호 뒤에 있는 첫 번째 문자열은 특정 확장 동작을 제공하는 클래스를 참조해야 하며, 해당 부분 문자열이 실제 클래스 이름에 포함된 경우 참조에서 부분 문자열 "Extension"을 생략할 수 있습니다. 그 후 단일 공백이 표시될 수 있으며, 닫는 중괄호가 발견될 때까지 이어지는 각 문자는 확장 구현에서 입력으로 사용됩니다.

.NET XAML 구현에서는 MarkupExtension 추상 클래스를 WPF에서 지원하는 모든 태그 확장과 기타 프레임워크 또는 기술의 기초로 사용합니다. WPF에서 특별히 구현하는 태그 확장은 종종 다른 기존 개체를 참조하거나 런타임에 평가될 개체에 대해 지연된 참조를 만들 수 있는 수단을 제공하기 위한 것입니다. 예를 들어 특정 속성이 일반적으로 사용하는 값 대신 {Binding} 태그 확장을 지정하여 간단한 WPF 데이터 바인딩을 수행합니다. 여러 WPF 태그 확장은 특성 구문을 사용하도록 설정하지 않으면 사용이 불가능한 속성에 대해 특성 구문을 사용하도록 설정합니다. 예를 들어 Style 개체는 중첩된 일련의 개체와 속성을 포함하는 비교적 복잡한 형식입니다. WPF의 스타일은 일반적으로 ResourceDictionary의 리소스로 정의된 다음, 리소스를 요청하는 두 WPF 태그 확장 중 하나를 통해 참조됩니다. 태그 확장은 다음 예제와 같이 속성 값의 평가를 리소스 조회로 연기하고 특성 구문에서 Style 형식을 사용하여 Style 속성 값을 제공할 수 있도록 합니다.

<Button Style="{StaticResource MyStyle}">My button</Button>

여기서 StaticResource는 태그 확장 구현을 제공하는 StaticResourceExtension 클래스를 식별합니다. 다음 문자열 MyStyle은 기본이 아닌 StaticResourceExtension 생성자에 대한 입력으로 사용되며, 확장 문자열에서 가져온 매개 변수는 요청된 ResourceKey를 선언합니다. MyStyle은 리소스로 정의된 Stylex:Key 값이어야 합니다. StaticResource 태그 확장 사용량은 로드 시 정적 리소스 조회 논리를 통해 Style 속성 값을 제공하는 데 리소스를 사용하도록 요청합니다.

태그 확장에 대한 자세한 내용은 XAML 태그 확장 및 WPF XAML을 참조하세요. 일반적인 .NET XAML 구현에 사용되는 태그 확장 및 기타 XAML 프로그래밍 기능에 대한 내용은 XAML 네임스페이스(x:) 언어 기능을 참조하세요. WPF 관련 태그 확장은 WPF XAML 확장을 참조하세요.

연결된 속성

연결된 속성은 XAML에서 도입된 프로그래밍 개념으로, 특정 형식에서 속성을 소유하고 정의할 수 있지만 모든 요소에서 특성 또는 속성 요소로 설정할 수 있습니다. 연결된 속성의 주요 용도는 태그 구조의 자식 요소가 모든 요소에서 광범위하게 공유된 개체 모델을 요구하지 않고 부모 요소에 정보를 보고할 수 있도록 하는 것입니다. 반대로 부모 요소에서 연결된 속성을 사용하여 자식 요소에 정보를 보고할 수 있습니다. 연결된 속성의 용도 및 연결된 속성을 만드는 방법에 대한 자세한 내용은 연결된 속성 개요를 참조하세요.

연결된 속성은 typeName.propertyName 조합도 지정한다는 측면에서 표면적으로는 속성 요소 구문과 유사한 구문을 사용합니다. 다음과 같은 두 가지 중요한 차이점이 있습니다.

  • 특성 구문을 통해 연결된 속성을 설정하는 경우에도 typeName.propertyName 조합을 사용할 수 있습니다. 연결된 속성은 속성 이름을 한정하는 것이 특성 구문의 요구 사항인 유일한 경우입니다.

  • 연결된 속성에 속성 요소 구문을 사용할 수도 있습니다. 그러나 일반적인 속성 요소 구문의 경우 지정하는 typeName은 속성 요소를 포함하는 개체 요소입니다. 연결된 속성을 참조하는 경우 typeName은 포함하는 개체 요소가 아니라 연결된 속성을 정의하는 클래스입니다.

연결된 이벤트

연결된 이벤트는 XAML에서 도입된 또 다른 프로그래밍 개념으로, 특정 형식으로 이벤트를 정의할 수 있지만 모든 개체 요소에 처리기를 연결할 수 있습니다. WOF 구현에서는 연결된 이벤트를 정의하는 형식이 서비스를 정의하는 정적 형식인 경우가 많으며, 연결된 이벤트가 서비스를 노출하는 형식의 라우트된 이벤트 별칭을 통해 노출되기도 합니다. 연결된 이벤트에 대한 처리기는 특성 구문을 통해 지정됩니다. 연결된 이벤트와 마찬가지로, 연결된 이벤트에 대한 특성 구문이 확장되어 typeName.eventName 사용을 허용합니다. 여기서 typeName은 연결된 이벤트 인프라에 대한 AddRemove 이벤트 처리기 접근자를 제공하는 클래스이고, eventName은 이벤트 이름입니다.

XAML 루트 요소 분석

다음 표에서는 루트 요소의 특성을 보여주는 일반적인 XAML 루트 요소를 세분화하여 보여줍니다.

attribute 설명
<Page 루트 요소의 여는 개체 요소
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 기본값(WPF) XAML 네임스페이스
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" XAML 언어 XAML 네임스페이스
x:Class="ExampleNamespace.ExampleCode" partial 클래스에 대해 정의된 코드 숨김에 태그를 연결하는 partial 클래스 선언
> 루트에 대한 개체 요소의 끝. 요소에 자식 요소가 포함되어 있으므로 개체가 아직 닫히지 않았습니다.

권장하지 않는 선택적 XAML 사용법

다음 섹션에서는 XAML 프로세서에서 기술적으로 지원하지만 XAML 원본이 포함된 애플리케이션을 개발할 때 사람이 읽을 수 있는 XAML 파일을 방해하는 세부 정보 표시 또는 기타 미적 문제를 생성하는 XAML 사용법에 대해 설명합니다.

선택적 속성 요소 사용법

선택적 속성 요소 사용법에는 XAML 프로세서가 암시적으로 간주하는 요소 콘텐츠 속성을 명시적으로 작성하는 것이 포함됩니다. 예를 들어 Menu의 콘텐츠를 선언할 때 MenuItems 컬렉션을 <Menu.Items> 속성 요소 태그로 명시적으로 선언하고, Menu의 모든 자식 요소가 MenuItem이어야 하고 Items 컬렉션에 배치되어야 하는 암시적 XAML 프로세서 동작을 사용하는 대신 각 MenuItem<Menu.Items> 내에 배치할 수 있습니다. 경우에 따라 선택적 사용법은 태그에 표시된 대로 개체 구조를 시각적으로 명확히 하는 데 도움이 될 수 있습니다. 또는 명시적 속성 요소를 사용하면 특성 값 내의 중첩된 태그 확장처럼 기술적으로는 작동하지만 시각적으로 혼동되는 태그를 방지할 수 있습니다.

전체 typeName.memberName 정규화된 특성

특성에 대한 typeName.memberName 양식은 라우트된 이벤트 사례보다 더 보편적으로 작동합니다. 그러나 다른 상황에서는 이 양식이 불필요하며 태그 스타일과 가독성 때문이라도 이 양식을 사용하지 말아야 합니다. 다음 예제에서는 Background 특성에 대한 세 가지 참조가 완전히 동일합니다.

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background가 작동하는 이유는 Button의 해당 속성에 대한 정규화된 조회가 성공(Background가 Control에서 상속됨)하고 Button이 개체 요소 또는 기본 클래스의 클래스이기 때문입니다. Control.Background가 작동하는 이유는 Control 클래스가 실제로 Background를 정의하고 ControlButton 기본 클래스이기 때문입니다.

그러나 다음 typeName.memberName 양식 예제는 작동하지 않으므로 주석으로 표시됩니다.

<!--<Button Label.Background="Blue">Does not work</Button> -->

LabelControl의 또 다른 파생 클래스이며, Label 개체 요소 내에서 Label.Background를 지정한 경우 이 사용법이 작동했을 것입니다. 그러나 LabelButton의 클래스 또는 기본 클래스가 아니므로 지정된 XAML 프로세서 동작은 Label.Background를 연결된 속성으로 처리하는 것입니다. Label.Background는 사용 가능한 연결된 속성이 아니므로 이 사용법은 실패합니다.

baseTypeName.memberName 속성 요소

baseTypeName.memberName 구문은 typeName.memberName 양식이 특성 구문에 대해 작동하는 방식과 비슷한 방식으로 속성 요소 구문에 대해 작동합니다. 예를 들어 다음 구문은 작동합니다.

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

여기서 속성 요소가 Button에 포함되었더라도 속성 요소에 Control.Background가 제공되었습니다.

하지만 특성에 대한 typeName.memberName 양식과 마찬가지로, baseTypeName.memberName은 태그에서 좋은 스타일이 아니므로 피해야 합니다.

참조