종속성 속성 값 우선 순위(WPF .NET)
WPF(Windows Presentation Foundation) 속성 시스템의 작동은 종속성 속성의 값에 영향을 줍니다. 이 문서에서는 WPF 속성 시스템 내에서 다양한 속성 기반 입력의 우선 순위가 종속성 속성의 유효 값을 결정하는 방법을 설명합니다.
필수 조건
이 문서에서는 독자들이 종속성 속성에 대한 기본 지식을 갖고 있으며 종속성 속성 개요를 읽었다고 가정합니다. XAML(Extensible Application Markup Language)에 익숙하고 WPF 애플리케이션을 작성하는 방법을 알고 있으면 이 문서의 예제를 따라 하는 데 도움이 됩니다.
WPF 속성 시스템
WPF 속성 시스템은 다양한 요소를 사용하여 관련 속성의 실시간 속성 유효성 검사, 지연 바인딩 및 속성 변경 알림과 같은 종속성 속성의 값을 결정합니다. 종속성 속성 값을 결정하는 데 사용되는 순서와 논리는 복잡하지만, 이를 알면 불필요한 속성 설정을 피하는 데 도움이 될 뿐 아니라 종속성 속성을 설정해도 예상 값이 발생하지 않은 이유를 파악할 수 있습니다.
여러 위치에서 설정되는 종속성 속성
다음 XAML 예제는 단추의 Background 속성에 대한 세 가지 "set" 작업이 해당 값에 어떤 영향을 줄 수 있는지 보여 줍니다.
<StackPanel>
<StackPanel.Resources>
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</StackPanel.Resources>
<Button Template="{StaticResource ButtonTemplate}" Background="Red">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Blue"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
Which color do you expect?
</Button>
</StackPanel>
이 예제에서 Background
속성은 로컬에서 Red
로 설정됩니다. 그러나 단추의 범위에서 선언된 암시적 스타일은 Background
속성을 Blue
로 설정하려고 시도합니다. 마우스가 단추 위에 있으면 암시적 스타일의 트리거가 Background
속성을 Yellow
로 설정하려고 시도합니다. 강제 변환 및 애니메이션을 제외하고 로컬에서 설정된 속성 값이 우선 순위가 가장 높기 때문에 mouseover 시에도 단추는 빨간색이 됩니다. 그러나 로컬에서 설정된 값을 단추에서 제거하면 단추는 스타일에서 Background
값을 가져옵니다. 스타일 내에서는 트리거가 우선하므로 단추는 mouseover 시 노란색이 되고 그렇지 않으면 파란색이 됩니다. 기본 템플릿에 하드 코드된 mouseover Background
값이 있으므로 예제는 단추의 기본 ControlTemplate을 바꿉니다.
종속성 속성 우선 순위 목록
다음 목록은 런타임 값을 종속성 속성에 할당할 때 속성 시스템이 사용하는 확정적 우선 순위 순서입니다. 가장 높은 우선 순위가 가장 먼저 나열됩니다.
속성 시스템 강제 변환. 강제 변환에 대한 자세한 내용은 강제 변환 및 애니메이션을 참조하세요.
활성 애니메이션 또는 보류 동작이 있는 애니메이션. 실제적인 효과를 주려면 애니메이션 값이 기준(애니메이션 효과를 주지 않은) 값보다 우선해야 합니다. 기준 값이 로컬에서 설정된 경우에도 마찬가지입니다. 자세한 내용은 강제 변환 및 애니메이션을 참조하세요.
로컬 값. XAML에서 특성 또는 속성 요소를 설정하거나 특정 인스턴스의 속성을 사용한 SetValue API 메서드 호출과 같은 "래퍼" 속성을 통해 로컬 값을 설정할 수 있습니다. 바인딩 또는 리소스를 통해 설정된 로컬 값은 직접 설정된 값과 우선 순위가 동일합니다.
TemplatedParent 템플릿 속성 값. 템플릿(ControlTemplate 또는 DataTemplate)에 의해 생성된 요소에는 TemplatedParent가 있습니다. 자세한 내용은 TemplatedParent를 참조하세요.
TemplatedParent
에 의해 지정된 템플릿 내에서 우선 순위는 다음과 같습니다.트리거
속성 집합(일반적으로 XAML 특성을 통해)
암시적 스타일 Style 속성에만 적용됩니다.
Style
값은 요소 형식과 일치하는 TargetType 값이 있는 스타일 리소스입니다. 스타일 리소스는 페이지 또는 애플리케이션 내에 있어야 합니다. 암시적 스타일 리소스에 대한 조회는 테마의 스타일 리소스로 확장되지 않습니다.스타일 트리거. 스타일 트리거는 명시적 또는 암시적 스타일 내의 트리거입니다. 스타일은 페이지 또는 애플리케이션 내에 있어야 합니다. 기본 스타일의 트리거는 우선 순위가 낮습니다.
템플릿 트리거. 템플릿 트리거는 직접 적용된 템플릿 또는 스타일 내에 있는 템플릿의 트리거입니다. 스타일은 페이지 또는 애플리케이션 내에 있어야 합니다.
스타일 setter 값. 스타일 setter 값은 스타일 내의 Setter에 의해 적용된 값입니다. 스타일은 페이지 또는 애플리케이션 내에 있어야 합니다.
기본 스타일, 즉 테마 스타일. 자세한 내용은 기본(테마) 스타일을 참조하세요. 기본 스타일 내에서 우선 순위는 다음과 같습니다.
활성 트리거.
Setter.
상속. 자식 요소의 일부 종속성 속성은 부모 요소에서 그 값을 상속합니다. 따라서 애플리케이션 전체에서 모든 요소에 속성 값을 설정할 필요가 없을 수도 있습니다. 자세한 내용은 속성 값 상속을 참조하세요.
종속성 속성 메타데이터의 기본값 종속성 속성은 속성의 속성 시스템 등록 중에 기본값이 설정될 수 있습니다. 종속성 속성을 상속하는 파생 클래스는 형식별로 종속성 속성 메타데이터(기본값 포함)를 재정의할 수 있습니다. 자세한 내용은 종속성 속성 메타데이터를 참조하세요. 상속된 속성의 경우 부모 요소의 기본값이 자식 요소의 기본값보다 우선합니다. 따라서 상속 가능한 속성이 설정되지 않은 경우 자식 요소의 기본값 대신 루트 또는 부모의 기본값이 사용됩니다.
TemplatedParent
TemplatedParent 우선 순위는 표준 애플리케이션 태그에서 직접 선언된 요소의 속성에는 적용되지 않습니다. TemplatedParent
개념은 템플릿 적용을 통해 생성된 시각적 트리 내의 자식 항목에만 존재합니다. 속성 시스템은 TemplatedParent
에 의해 지정된 템플릿에서 요소의 속성 값을 검색할 때 해당 요소를 만든 템플릿을 검색합니다. TemplatedParent
템플릿의 속성 값은 일반적으로 요소에서 로컬로 설정된 값처럼 작동하지만 템플릿이 잠재적으로 공유되기 때문에 실제 로컬 값보다 우선 순위가 낮습니다. 자세한 내용은 TemplatedParent를 참조하세요.
스타일 속성
Style 속성을 제외한 모든 종속성 속성에 동일한 우선 순위가 적용됩니다. Style
속성은 자체에 스타일을 지정할 수 없다는 점에서 고유합니다. Style
속성을 강제 변환하거나 애니메이션 효과를 주는 것은 권장되지 않습니다(또한 Style
속성에 애니메이션 효과를 주려면 사용자 지정 애니메이션 클래스가 필요합니다). 따라서 모든 우선 순위 항목이 적용되지는 않습니다. Style
속성을 설정하는 방법은 다음 세 가지뿐입니다.
명시적 스타일. 요소의
Style
속성이 직접 설정됩니다.Style
속성 값은 로컬 값인 것처럼 작동하며 우선 순위 목록의 항목 3과 우선 순위가 같습니다. 대부분의 시나리오에서 명시적 스타일은 인라인으로 정의되지 않고, 대신 리소스로 명시적으로 참조됩니다(예:Style="{StaticResource myResourceKey}"
).암시적 스타일.
Style
요소의 속성이 직접 설정되지 않습니다. 대신 스타일은 페이지 또는 애플리케이션 내의 특정 수준에 있고 스타일이 적용되는 요소의 형식과 일치하는 리소스 키가 있을 때 적용됩니다(예:<Style TargetType="x:Type Button">
). 형식은 정확히 일치해야 합니다. 예를 들어<Style TargetType="x:Type Button">
은MyButton
이Button
에서 파생되더라도MyButton
형식에 적용되지 않습니다.Style
속성 값의 우선 순위는 우선 순위 목록의 항목 5와 같습니다. DependencyPropertyHelper.GetValueSource 메서드를 호출하고,Style
속성을 전달하고, 결과에서ImplicitStyleReference
를 확인하여 암시적 스타일 값을 검색할 수 있습니다.기본 스타일, 즉 테마 스타일.
Style
요소의 속성이 직접 설정되지 않습니다. 대신 WPF 프레젠테이션 엔진의 런타임 테마 평가에서 제공됩니다. 런타임 전에Style
속성 값은null
입니다.Style
속성 값의 우선 순위는 우선 순위 목록의 항목 9와 같습니다.
기본(테마) 스타일
WPF와 함께 제공되는 모든 컨트롤에는 테마에 따라 달라질 수 있는 기본 스타일이 있으므로 기본 스타일을 테마 스타일이라고도 합니다.
ControlTemplate은 컨트롤의 기본 스타일 내에서 중요한 항목입니다. ControlTemplate
는 스타일 Template 속성의 setter 값입니다. 기본 스타일에 템플릿이 포함되지 않은 경우 사용자 지정 스타일의 일부로 사용자 지정 템플릿이 없는 컨트롤에는 시각적인 모양이 전혀 없습니다. 템플릿은 컨트롤의 시각적 모양을 정의할 뿐만 아니라 템플릿의 시각적 트리에 있는 속성과 해당 컨트롤 클래스 간의 연결도 정의합니다. 각 컨트롤은 템플릿을 교체하지 않고 컨트롤의 시각적인 모양에 영향을 줄 수 있는 속성의 집합을 노출합니다. 예를 들어 ScrollBar 구성 요소인 Thumb 컨트롤의 기본 시각적 모양을 생각해 보세요.
Thumb 컨트롤에는 사용자 지정 가능한 특정 속성이 있습니다. Thumb
컨트롤의 기본 템플릿은 중첩된 Border 구성 요소 몇 개가 있는 기본 구조 또는 시각적 트리를 만들어 3D 가장자리의 모양을 만듭니다. 템플릿 내에서 Thumb
클래스에 의해 사용자 지정 가능하도록 되어 있는 속성은 TemplateBinding을 통해 노출됩니다. Thumb
컨트롤의 기본 템플릿에는 템플릿 바인딩을 Background 또는 BorderThickness 같은 속성과 공유하는 다양한 테두리 속성이 있습니다. 그러나 속성 또는 시각적 개체 배열의 값이 템플릿에서 하드 코드되거나 테마에서 직접 제공되는 값에 바인딩되는 경우 전체 템플릿을 바꿔야 해당 값을 변경할 수 있습니다. 일반적으로 속성이 템플릿 부모에서 제공되고 TemplateBinding
에 의해 노출되지 않는 경우 속성 값을 대상으로 지정할 편리한 방법이 없으므로 스타일이 속성 값을 변경할 수 없습니다. 그러나 해당 속성은 적용된 템플릿의 속성 값 상속이나 기본값의 영향을 받을 수 있습니다.
기본 스타일은 그 정의에서 TargetType을 지정합니다. 런타임 테마 평가는 기본 스타일의 TargetType
과 컨트롤의 DefaultStyleKey 속성을 대조합니다. 반면 암시적 스타일의 조회 동작은 컨트롤의 실제 형식을 사용합니다. 파생 클래스는 DefaultStyleKey
값을 상속하므로 연결된 스타일이 없을 수 있는 파생 요소는 기본 시각적 모양을 갖습니다. 예를 들어 MyButton
이 Button에서 파생되는 경우 MyButton
은 Button
의 기본 템플릿을 상속합니다. 파생 클래스는 종속성 속성 메타데이터에서 DefaultStyleKey
의 기본값을 재정의할 수 있습니다. 따라서 MyButton
에 다른 시각적 개체 표현을 원하는 경우 MyButton
에서 DefaultStyleKey
의 종속성 속성 메타데이터를 재정의한 다음 MyButton
컨트롤을 사용하여 패키지할 템플릿을 포함한 관련 기본 스타일을 정의할 수 있습니다. 자세한 내용은 컨트롤 작성 개요를 참조하세요.
동적 리소스
동적 리소스 참조 및 바인딩 작업은 설정된 위치의 우선 순위를 갖습니다. 예를 들어 로컬 값에 적용된 동적 리소스의 우선 순위는 우선 순위 목록의 항목 3과 동일합니다. 또 다른 예로 기본 스타일 내의 속성 setter에 적용되는 동적 리소스 바인딩의 우선 순위는 우선 순위 목록의 항목 9와 동일합니다. 동적 리소스 참조 및 바인딩은 애플리케이션의 런타임 상태에서 값을 얻어야 하므로 지정된 속성의 속성 값 우선 순위를 결정하는 프로세스는 런타임까지 확장됩니다.
동적 리소스 참조는 기술적으로 속성 시스템의 일부가 아니며, 우선 순위 목록과 상호 작용하는 자체 조회 순서를 갖습니다. 기본적으로 동적 리소스 참조의 우선 순위는 요소, 페이지 루트, 애플리케이션, 테마, 시스템 순서입니다. 자세한 내용은 XAML 리소스를 참조하세요.
동적 리소스 참조 및 바인딩은 설정된 위치의 우선 순위를 갖지만 값은 지연됩니다. 이로 인한 결과 중 하나는 동적 리소스나 바인딩을 로컬 값에 설정하는 경우 로컬 값을 변경하면 동적 리소스나 바인딩이 완전히 대체된다는 것입니다. ClearValue 메서드를 호출하여 로컬에 설정된 값을 지우더라도 동적 리소스나 바인딩은 복원되지 않습니다. 실제로 동적 리소스 또는 바인딩이 있는 속성(리터럴 로컬 값 없음)에서 ClearValue
를 호출하면 동적 리소스 또는 바인딩이 지워집니다.
SetCurrentValue
SetCurrentValue 메서드도 속성을 설정할 수 있는 방법이지만 우선 순위 목록에 없습니다. SetCurrentValue
를 사용하여 이전 값의 소스를 덮어쓰지 않고 속성 값을 변경할 수 있습니다. 예를 들어 속성이 트리거에 의해 설정된 후 SetCurrentValue
를 사용하여 다른 값을 할당하는 경우 다음 트리거 작업은 속성을 다시 트리거 값으로 설정합니다. 속성 값에 로컬 값의 우선 순위를 제공하지 않고 속성 값을 설정하려는 경우 항상 SetCurrentValue
를 사용할 수 있습니다. 마찬가지로 SetCurrentValue
를 사용하여 바인딩을 덮어쓰지 않고 속성 값을 변경할 수 있습니다.
강제 변환 및 애니메이션
강제 변환과 애니메이션은 모두 기준 값에서 작동합니다. 기준 값은 우선 순위가 가장 높은 종속성 속성 값으로, 항목 2에 도달할 때까지 우선 순위 목록에서 위로 올라가며 평가하여 결정됩니다.
애니메이션이 특정 동작의 From 및 To 속성 값을 지정하지 않거나 완료될 때 애니메이션이 의도적으로 기준 값으로 되돌아가는 경우 기준 값은 애니메이션 값에 영향을 줄 수 있습니다. 이를 실제로 확인하려면 대상 값 샘플 애플리케이션을 실행하세요. 샘플에서 사각형 높이에 어떤 From
값과도 다른 초기 로컬 값을 설정해 봅니다. 샘플 애니메이션은 기준 값 대신 From
값을 사용하여 즉시 시작됩니다. Stop를 FillBehavior로 지정하면 완료 시 애니메이션은 속성 값을 기준 값으로 다시 설정합니다. 애니메이션이 종료된 후에는 일반적 우선 순위가 기준 값 결정에 사용됩니다.
각각 우선 순위가 다른 여러 애니메이션을 단일 속성에 적용할 수 있습니다. WPF 프레젠테이션 엔진은 우선 순위가 가장 높은 애니메이션을 적용하는 대신 애니메이션이 정의된 방식과 애니메이션 값의 형식에 따라 애니메이션 값을 합성할 수 있습니다. 자세한 내용은 애니메이션 개요를 참조하세요.
강제 변환은 우선 순위 목록의 맨 위에 있습니다. 실행 중인 애니메이션에도 값 강제 변환이 적용됩니다. WPF의 일부 기존 종속성 속성에는 기본 제공 강제 변환이 있습니다. 사용자 지정 종속성 속성의 경우 속성을 만들 때 메타데이터의 일부로 전달하는 CoerceValueCallback을 작성하여 강제 변환 동작을 정의할 수 있습니다. 파생 클래스에서 해당 속성의 메타데이터를 재정의하여 기존 속성의 강제 변환 동작을 재정의할 수도 있습니다. 강제 변환은 강제 변환에 대한 제약 조건이 존재할 때 적용되는 방식으로 기준 값과 상호 작용하지만 기준 값은 계속 유지됩니다. 따라서 강제 변환의 제약 조건이 나중에 해제되면 강제 변환은 가능한 가장 가까운 값을 기준 값에 반환하고, 모든 제약 조건이 해제되는 즉시 속성에 강제 변환이 미치는 영향이 중단될 수 있습니다. 강제 변환 동작에 대한 자세한 내용은 종속성 속성 콜백 및 유효성 검사를 참조하세요.
트리거 동작
컨트롤은 해당 기본 스타일의 일부로 트리거 동작을 정의하는 경우가 많습니다. 컨트롤에 로컬 속성을 설정하면 이러한 트리거와 충돌하여 트리거가 사용자 기반 이벤트에 (시각적으로 또는 동작으로) 응답하지 못할 수 있습니다. 속성 트리거는 일반적으로 IsSelected 또는 IsEnabled와 같은 상태 속성을 제어하는 데 사용됩니다. 예를 들어 기본적으로 Button을 사용하지 않는 경우 테마 스타일 트리거(IsEnabled
이 false
)는 Button
이 회색으로 표시되도록 Foreground 값을 설정합니다. 로컬 Foreground
값을 설정한 경우 Button
이 사용되지 않더라도 우선 순위가 높은 로컬 속성 값이 테마 스타일 Foreground
값을 무효화합니다. 컨트롤의 테마 수준 트리거 동작을 재정의하는 속성 값을 설정할 때는 해당 컨트롤에 대해 의도한 사용자 환경을 지나치게 방해하지 않도록 주의해야 합니다.
ClearValue
ClearValue 메서드는 요소에 대한 종속성 속성의 로컬로 적용된 값을 모두 지웁니다. 그러나 ClearValue
를 호출한다고 해서 속성을 등록할 때 메타데이터에 설정된 기본값이 새 유효 값으로 보장되는 것은 아닙니다. 우선 순위 목록의 다른 모든 참가자는 여전히 활성 상태이며, 로컬로 설정된 값만 제거됩니다. 예를 들어 테마 스타일이 있는 속성에서 ClearValue
를 호출하면 테마 스타일 값이 메타데이터 기반 기본값이 아니라 새 값으로 적용됩니다. 속성 값을 등록된 메타데이터 기본값으로 설정하려면 종속성 속성 메타데이터를 쿼리하여 기본 메타데이터 값을 가져오고 로컬에서 SetValue 호출을 사용하여 속성 값을 설정합니다.
참고 항목
.NET Desktop feedback