XAML 로드 및 종속성 속성(WPF .NET)

XAML(Extensible Application Markup Language) 프로세서의 WPF(Windows Presentation Foundation) 구현은 기본적으로 종속성 속성을 인식합니다. 따라서 XAML 프로세서는 WPF 속성 시스템 메서드를 사용하여 XAML을 로드하고 종속성 속성 특성을 처리하며, GetValueSetValue 같은 WPF 속성 시스템 메서드를 사용하여 종속성 속성 래퍼를 완전히 무시합니다. 따라서 사용자 지정 종속성 속성의 속성 래퍼에 사용자 지정 논리를 추가하면, 속성 값이 XAML에서 설정되는 경우 XAML 프로세서에서 호출 되지 않습니다.

중요

.NET 7 및 .NET 6에 관한 데스크톱 가이드 설명서는 제작 중입니다.

필수 구성 요소

이 문서에서는 독자들이 종속성 속성에 대한 기본 지식을 갖고 있으며 종속성 속성 개요를 읽었다고 가정합니다. XAML(Extensible Application Markup Language)에 익숙하고 WPF 애플리케이션을 작성하는 방법을 알고 있으면 이 문서의 예제를 따라 하는 데 도움이 됩니다.

WPF XAML 로더 성능

WPF XAML 프로세서가 종속성 속성의 속성 래퍼를 사용하는 대신 종속성 속성의 값을 설정하기 위해 직접 SetValue를 호출하면 계산 비용이 적게 들어갑니다.

XAML 프로세서가 속성 래퍼를 사용했다면, 프로세서는 태그에 표시된 형식 및 멤버 관계만을 기반으로 하여 지원 코드의 전체 개체 모델을 유추해야 합니다. 형식은 xmlns 및 어셈블리 특성 조합을 사용하고, 멤버를 식별하고, 특성으로 설정할 수 있는 멤버를 결정하고, 지원되는 속성 값 형식을 확인하여 태그에서 식별할 수 있지만, 이렇게 하려면 PropertyInfo를 이용한 광범위한 리플렉션이 필요합니다.

WPF 속성 시스템은 지정된 DependencyObject 파생 형식에서 구현된 종속성 속성의 스토리지 테이블을 유지합니다. XAML 프로세서는 이 테이블을 사용하여 종속성 속성에 대한 종속성 속성 식별자를 유추합니다. 예를 들어 일반적으로 ABC라는 종속성 속성에 대한 종속성 속성 식별자는 ABCProperty입니다. XAML 프로세서는 종속성 속성 식별자를 사용하는 포함 형식에서 SetValue 메서드를 호출하여 종속성 속성의 값을 효율적으로 설정할 수 있습니다.

종속성 속성 래퍼에 대한 자세한 내용은 사용자 지정 종속성 속성을 참조하세요.

사용자 지정 종속성 속성의 의미

WPF XAML 프로세서는 속성 래퍼를 무시하고 SetValue를 직접 호출하여 종속성 속성 값을 설정합니다. 따라서 사용자 지정 종속성 속성의 set 접근자에 추가 논리를 배치해선 안 됩니다. 이 논리는 속성 값이 XAML에서 설정되어도 실행되지 않기 때문입니다. set 접근자는 SetValue 호출만 포함해야 합니다.

마찬가지로, 속성 값을 가져오는 WPF XAML 프로세서의 측면은 속성 래퍼를 무시하고 GetValue를 직접 호출합니다. 또한 사용자 지정 종속성 속성의 get 접근자에 추가 논리를 배치해선 안 됩니다. 이 논리는 속성 값을 XAML에서 읽어도 실행되지 않기 때문입니다. get 접근자는 GetValue 호출만 포함해야 합니다.

래퍼가 있는 종속성 속성 예제

다음 예에서는 속성 래퍼를 사용한 권장되는 종속성 속성 정의를 확인할 수 있습니다. 종속성 속성 식별자는 public static readonly 필드로 저장되며, getset 접근자에는 종속성 속성 값을 반환 하는 필수 WPF 속성 시스템 메서드 외에는 어떠한 코드도 포함되어 있지 않습니다. 종속성 속성 값 변경 시 실행해야 하는 코드가 있다면, 코드를 종속성 속성의 PropertyChangedCallback에 배치하는 것이 좋습니다. 자세한 내용은 속성 변경 콜백을 참조하세요.

// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
public static readonly DependencyProperty AquariumGraphicProperty =
    DependencyProperty.Register(
      name: "AquariumGraphic",
      propertyType: typeof(Uri),
      ownerType: typeof(Aquarium),
      typeMetadata: new FrameworkPropertyMetadata(
          defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
          flags: FrameworkPropertyMetadataOptions.AffectsRender,
          propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
    );

// Property wrapper with get & set accessors.
public Uri AquariumGraphic
{
    get => (Uri)GetValue(AquariumGraphicProperty);
    set => SetValue(AquariumGraphicProperty, value);
}

// Property-changed callback.
private static void OnUriChanged(DependencyObject dependencyObject, 
    DependencyPropertyChangedEventArgs e)
{
    // Some custom logic that runs on effective property value change.
    Uri newValue = (Uri)dependencyObject.GetValue(AquariumGraphicProperty);
    Debug.WriteLine($"OnUriChanged: {newValue}");
}
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
    DependencyProperty.Register(
        name:="AquariumGraphic",
        propertyType:=GetType(Uri),
        ownerType:=GetType(Aquarium),
        typeMetadata:=New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
            flags:=FrameworkPropertyMetadataOptions.AffectsRender,
            propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))

' Property wrapper with get & set accessors.
Public Property AquariumGraphic As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set
        SetValue(AquariumGraphicProperty, Value)
    End Set
End Property

' Property-changed callback.
Private Shared Sub OnUriChanged(dependencyObject As DependencyObject,
                                e As DependencyPropertyChangedEventArgs)
    ' Some custom logic that runs on effective property value change.
    Dim newValue As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri)
    Debug.WriteLine($"OnUriChanged: {newValue}")
End Sub

참고 항목