연결된 속성 개요(WPF .NET)

연결된 속성은 XAML(Extensible Application Markup Language) 개념입니다. 연결된 속성을 사용하면 요소가 그 개체 모델에서 이러한 추가 속성을 정의하지 않더라도 DependencyObject에서 파생되는 XAML 요소에서 추가 속성/값 쌍을 설정할 수 있습니다. 추가 속성은 전역적으로 액세스할 수 있습니다. 연결된 속성은 대체로 기존 속성 래퍼가 없는 특수한 형식의 종속성 속성으로 정의됩니다.

중요

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

필수 구성 요소

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

연결된 속성을 사용하는 이유

연결된 속성을 사용하면 자식 요소가 부모 요소에 정의된 속성의 고유 값을 지정할 수 있습니다. 일반적인 시나리오는 UI에서 부모 요소가 자식 요소를 어떻게 렌더링해야 하는지 자식 요소입니다. 예를 들어 DockPanel.DockDockPanel 자체가 아닌 DockPanel의 자식 요소에 설정되어 있기 때문에 연결된 속성입니다. DockPanel 클래스는 DockProperty라는 정적 DependencyProperty 필드를 정의한 다음, GetDockSetDock 메서드를 연결된 속성에 대한 공용 접근자로 제공합니다.

XAML의 연결된 속성

XAML에서는 <attached property provider type>.<property name> 구문을 사용하여 연결된 속성을 설정합니다. 여기서 연결된 속성 공급자는 연결된 속성을 정의하는 클래스입니다. 다음 예제에서는 DockPanel의 자식 요소가 DockPanel.Dock 속성 값을 설정할 수 있는 방법을 보여줍니다.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

사용법은 인스턴스 이름이 아닌 연결된 속성(예: DockPanel)을 소유하고 등록하는 형식을 참조한다는 점에서 정적 속성과 비슷합니다.

XAML 특성을 사용하여 연결된 속성을 지정하는 경우 설정 동작만 적용할 수 있습니다. 스타일의 트리거처럼 값을 비교하는 간접 메커니즘이 있더라도 XAML에서 속성을 직접 가져올 수 없습니다.

WPF의 연결된 속성

연결된 속성은 XAML 개념이지만 종속성 속성은 WPF 개념입니다. WPF에서 WPF 형식의 UI 관련 연결된 속성은 대부분 종속성 속성으로 구현됩니다. 종속성 속성으로 구현되는 WPF 연결 속성은 메타데이터의 기본값을 포함한 속성 메타데이터와 같은 종속성 속성 개념을 지원합니다.

연결된 속성 사용 모델

모든 개체가 연결된 속성 값을 설정할 수 있지만, 값을 설정해도 실제 결과를 생성하거나 다른 개체에서 값이 사용된다는 것을 의미하지는 않습니다. 연결된 속성의 주요 목적은 다양한 클래스 계층 구조 및 논리적 관계의 개체가 연결된 속성을 정의하는 형식에 일반 정보를 보고하는 방법을 제공하는 것입니다. 연결된 속성 사용법은 일반적으로 다음 모델 중 하나를 따릅니다.

  • 연결된 속성을 정의하는 형식은 연결된 속성의 값을 설정하는 요소의 부모입니다. 부모 형식은 개체 트리 구조에서 작동하고, 값을 가져오고, 이러한 값에 대해 어떤 방식으로든 작용하는 내부 논리를 통해 자식 개체를 반복합니다.
  • 연결된 속성을 정의하는 형식은 가능한 다양한 부모 요소와 콘텐츠 모델에 대한 자식 요소로 사용됩니다.
  • 연결된 속성을 정의하는 형식은 서비스를 나타냅니다. 다른 형식은 연결된 속성에 대한 값을 설정합니다. 그런 다음 속성을 설정하는 요소를 서비스의 컨텍스트에서 계산하는 경우, 연결된 속성 값은 서비스 클래스의 내부 논리를 통해 얻습니다.

부모가 정의한 연결된 속성의 예

WPF가 연결된 속성을 정의하는 일반적인 시나리오는 부모 요소가 자식 요소 컬렉션을 지원하고, 부모 요소가 각 자식 요소에서 보고한 데이터를 기반으로 동작을 구현하는 경우입니다.

DockPanelDockPanel.Dock 연결된 속성을 정의합니다. DockPanel에는 클래스 수준 코드, 특히 렌더링 논리의 일부인 MeasureOverrideArrangeOverride가 있습니다. DockPanel 인스턴스는 직계 자식 요소가 DockPanel.Dock 값을 설정했는지 확인합니다. 설정한 경우 이러한 값은 각 자식 요소에 적용되는 렌더링 논리에 대한 입력이 됩니다. 이론적으로는 연결된 속성이 직계 부모 이외의 요소에 영향을 줄 수 있지만, 중첩 DockPanel 인스턴스에 대해 정의된 동작은 해당 직계 자식 요소 컬렉션과만 상호 작용합니다. 따라서 DockPanel 부모가 없는 요소에서 DockPanel.Dock를 설정하면 오류나 예외가 발생하지 않으며 어떤 DockPanel도 사용하지 않는 전역 속성 값을 만들었을 것입니다.

코드의 연결된 속성

속성이 CLR 네임스페이스 외부에서 설정될 수 있으므로 WPF의 연결된 속성에는 일반적인 CLR getset 래퍼 메서드가 없습니다. XAML을 구문 분석할 때 XAML 프로세서가 이러한 값을 설정하도록 허용하려면 연결된 속성을 정의하는 클래스가 Get<property name>Set<property name> 형식의 전용 접근자 메서드를 구현해야 합니다.

다음 예제와 같이 전용 접근자 메서드를 사용하여 코드에서 연결된 속성을 얻고 설정할 수도 있습니다. 이 예제에서 myTextBoxTextBox 클래스의 인스턴스입니다.

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

myTextBoxmyDockPanel의 자식 요소로 추가하지 않으면 SetDock를 호출해도 예외가 발생하거나 영향을 주지 않습니다. DockPanel의 자식 요소에 설정된 DockPanel.Dock 값만 렌더링에 영향을 줄 수 있으며, 자식 요소를 DockPanel에 추가하기 전에 값을 설정하든 후에 설정하든 관계없이 렌더링은 동일합니다.

코드의 관점에서 연결된 속성은 속성 접근자 대신 메서드 접근자가 있는 지원 필드와 유사하며, 이러한 개체에서 먼저 정의할 필요 없이 모든 개체에서 설정할 수 있습니다.

연결된 속성 메타데이터

연결된 속성에 대한 메타데이터는 일반적으로 종속성 속성과 차이가 없습니다. 연결된 속성을 등록하는 경우 FrameworkPropertyMetadata를 사용하여 속성이 렌더링 또는 측정에 영향을 주는지 여부와 같은 속성의 특징을 지정합니다. 연결된 속성 메타데이터를 재정의하여 기본값을 지정하면 해당 값은 재정의 클래스의 인스턴스에서 암시적 연결된 속성의 기본값이 됩니다. 연결된 속성 값을 설정하지 않으면 Get<property name> 접근자를 사용하여 속성을 쿼리할 때 메타데이터를 지정한 클래스 인스턴스와 함께 기본값이 보고됩니다.

속성에서 속성 값 상속을 사용하도록 설정하려면 연결되지 않은 종속성 속성 대신 연결된 속성을 사용합니다. 자세한 내용은 속성 값 상속을 참조하세요.

사용자 지정 연결된 속성

연결된 속성을 만들어야 하는 경우

다음과 같은 경우 연결된 속성을 만들면 유용합니다.

  • 정의 클래스가 아닌 다른 클래스에 사용할 수 있는 속성 설정 메커니즘이 필요합니다. 일반적인 시나리오는 UI 레이아웃입니다. 예를 들어 DockPanel.Dock, Panel.ZIndexCanvas.Top은 모두 기존 레이아웃 속성의 예입니다. 레이아웃 시나리오에서 레이아웃 제어 요소의 자식 요소는 레이아웃 부모에 대한 레이아웃 요구 사항을 표현하고 부모가 정의한 연결된 속성의 값을 설정할 수 있습니다.

  • 클래스 중 하나가 서비스를 나타내며, 다른 클래스가 서비스를 보다 투명하게 통합하기를 원합니다.

  • 속성 창을 통해 속성을 편집하는 기능과 같은 Visual Studio WPF Designer 지원을 원합니다. 자세한 내용은 컨트롤 제작 개요를 참조하세요.

  • 속성 값 상속을 사용하려고 합니다.

연결된 속성을 만드는 방법

클래스가 다른 형식에서만 사용하기 위해 연결된 속성을 정의하는 경우 클래스는 DependencyObject에서 파생할 필요가 없습니다. 그렇지 않은 경우 DependencyObject에서 클래스를 파생시켜 연결된 속성도 종속성 속성으로 사용하는 WPF 모델을 따릅니다.

DependencyProperty 형식의 public static readonly 필드를 선언하여 연결된 속성을 정의 클래스에서 종속성으로 정의합니다. 그런 다음, 종속성 속성 식별자라고도 하는 필드에 RegisterAttached 메서드의 반환 값을 할당합니다. 식별자 필드 <property name>Property의 이름을 지정하여 필드를 필드가 나타내는 속성과 구분하는 WPF 속성 명명 규칙을 따릅니다. 또한 속성 시스템이 연결된 속성에 액세스할 수 있게 하는 정적 Get<property name>Set<property name> 접근자 메서드를 제공합니다.

다음 예제에서는 RegisterAttached 메서드를 사용하여 종속성 속성을 등록하는 방법과 접근자 메서드를 정의하는 방법을 보여줍니다. 이 예제에서 연결된 속성의 이름은 HasFish이므로 식별자 필드의 이름이 HasFishProperty로 지정되고, 접근자 메서드의 이름은 GetHasFishSetHasFish로 지정됩니다.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

get 접근자

get 접근자 메서드 시그니처는 public static object Get<property name>(DependencyObject target)이며 다음과 같습니다.

  • target은 연결된 속성을 읽어 올 DependencyObject입니다. target 형식은 DependencyObject보다 구체적일 수 있습니다. 예를 들어 연결된 속성이 UIElement 인스턴스에서 설정되므로 DockPanel.GetDock 접근자 메서드는 targetUIElement로 형식화합니다. UiElementDependencyObject에서 간접적으로 파생됩니다.
  • 반환 형식은 object보다 구체적일 수 있습니다. 예를 들어 반환 값이 Dock 열거형이어야 하므로 GetDock 메서드는 반환된 값을 Dock로 형식화합니다.

참고

연결된 속성의 get 접근자는 Visual Studio 또는 Blend for Visual Studio와 같은 디자인 도구에서 데이터 바인딩을 지원하는 데 필요합니다.

set 접근자

set 접근자 메서드 시그니처는 public static void Set<property name>(DependencyObject target, object value)이며 다음과 같습니다.

  • target은 연결된 속성이 기록되는 DependencyObject입니다. target 형식은 DependencyObject보다 구체적일 수 있습니다. 예를 들어 연결된 속성이 UIElement 인스턴스에서 설정되므로 SetDock 메서드는 targetUIElement로 형식화합니다. UiElementDependencyObject에서 간접적으로 파생됩니다.
  • value 형식은 object보다 구체적일 수 있습니다. 예를 들어 SetDock 메서드에는 Dock 값이 필요합니다. XAML 로더는 태그 문자열에서 연결된 속성 값을 나타내는 value 형식을 생성할 수 있어야 합니다. 따라서 사용하는 형식에 대한 형식 변환, 값 직렬 변환기 또는 태그 확장 지원이 필요합니다.

연결된 속성 특성

WPF는 리플렉션 프로세스 및 리플렉션의 일반 사용자와 디자이너와 같은 속성 정보에 연결된 속성에 대한 정보를 제공하기 위한 여러 .NET을 정의합니다. 모든 연결된 속성의 전역 목록이 사용자에게 표시되지 않도록 디자이너는 WPF에서 정의한 .NET 특성을 사용하여 속성 창에 표시되는 속성을 제한합니다. 고유의 사용자 지정 연결된 속성에 이러한 특성을 적용할 수 있습니다. .NET 특성의 용도와 구문은 다음 참조 페이지에 설명되어 있습니다.

자세한 정보

  • 연결된 속성을 만드는 방법에 대한 자세한 내용은 연결된 속성 등록을 참조하세요.
  • 종속성 속성 및 연결된 속성에 대한 고급 사용 시나리오는 사용자 지정 종속성 속성을 참조하세요.
  • 속성을 연결된 속성 및 종속성 속성으로 등록하고 기존 속성 래퍼를 포함할 수 있습니다. 이러한 방식으로 속성 래퍼를 사용하여 요소에서, 그리고 XAML 연결된 속성 구문을 사용하여 다른 요소에서 속성을 설정할 수 있습니다. 예제를 보려면 FrameworkElement.FlowDirection를 참조하세요.

참고 항목