패널은 XAML(Extensible Application Markup Language) 레이아웃 시스템이 실행되고 앱 UI가 렌더링될 때, 포함된 자식 요소에 대한 레이아웃 동작을 제공하는 개체입니다.
중요 API: 패널, ArrangeOverride, MeasureOverride
Panel 클래스에서 사용자 지정 클래스를 파생시켜 XAML 레이아웃에 대한 사용자 지정 패널 을 정의할 수 있습니다. MeasureOverride와 ArrangeOverride를 재정의하여, 자식 요소를 측정하고 정렬하는 논리를 제공함으로써 패널의 동작을 구현합니다.
Panel 기본 클래스
사용자 지정 패널 클래스를 정의하려면 Panel 클래스에서 직접 파생하거나 Grid 또는 StackPanel과 같이 봉인되지 않은 실제 패널 클래스 중 하나에서 파생할 수 있습니다. 이미 레이아웃 동작이 있는 패널의 기존 레이아웃 논리를 해결하기 어려울 수 있으므로 패널파생하기가 더 쉽습니다. 또한 동작이 있는 패널에는 패널의 레이아웃 기능과 관련이 없는 기존 속성이 있을 수 있습니다.
패널에서 귀하의 사용자 지정 패널은 다음 API를 상속합니다.
- Children 속성입니다.
- Background, ChildrenTransitions, IsItemsHost 속성과 종속성 속성 식별자입니다. 이러한 속성은 가상이 아니므로 보통 재정의하거나 대체하지 않습니다. 사용자 지정 패널 시나리오에는 일반적으로 이러한 속성이 필요하지 않으며 값을 읽는 경우에도 필요하지 않습니다.
- 레이아웃 재정의 메서드 MeasureOverride 및 ArrangeOverride. 이는 원래 FrameworkElement에 의해 정의되었습니다. 기본 Panel 클래스는 재정의하지 않지만 Grid 같은 실제 패널에는 네이티브 코드로 구현되고 시스템에서 실행되는 재정의 구현이 있습니다. ArrangeOverride 및 MeasureOverride에 대한 새로운(또는 추가적인) 구현을 제공하는 것은 사용자 지정 패널을 정의하는 데 필요한 많은 노력입니다.
- 다른 모든 FrameworkElement, UIElement 및 DependencyObject의 API(예: Height, Visibility 등) 레이아웃 재정의에서 이러한 속성의 값을 참조하는 경우도 있지만 가상이 아니므로 일반적으로 재정의하거나 대체하지 않습니다.
여기서는 XAML 레이아웃 개념을 설명하는 데 중점을 두므로 사용자 지정 패널이 레이아웃에서 어떻게 동작할 수 있고 어떻게 동작해야 하는지에 대한 모든 가능성을 고려할 수 있습니다. 바로 시작해서 사용자 지정 패널 구현 예제를 보고 싶다면, BoxPanel을 참조하세요. 이는 사용자 지정 패널의 예제입니다.
Children 속성
Children 속성은 Panel에서 파생된 모든 클래스가 컬렉션에 포함된 자식 요소를 저장할 위치로 Children 속성을 사용할 있으므로 사용자 지정 패널과 관련이 있습니다. Children은 Panel 클래스의 XAML 콘텐츠 속성으로 지정되며, Panel에서 파생된 모든 클래스는 XAML 콘텐츠 속성 동작을 상속받을 수 있습니다. 속성이 XAML 콘텐츠 속성으로 지정된 경우, 즉 XAML 마크업에서 해당 속성을 지정할 때 속성 요소를 생략할 수 있으며, 값은 마크업의 자식 요소("콘텐츠")로 설정됩니다. 새로운 동작을 정의하지 않는 Panel으로부터 CustomPanel이라는 클래스를 파생하는 경우에도 이 마크업을 사용할 수 있습니다.
<local:CustomPanel>
<Button Name="button1"/>
<Button Name="button2"/>
</local:CustomPanel>
XAML 파서가 이 태그를 읽을 때 Children은 모든 패널에서 파생된 형식에 대한 XAML 콘텐츠 속성이라는 점에서 파서는 두 Button 요소를 Children 속성의 UIElementCollection 값에 추가합니다. XAML 콘텐츠 속성은 UI 정의를 위한 XAML 마크업에서 부모-자식 관계를 간소화하고 쉽게 구성할 수 있게 합니다. XAML 콘텐츠 속성 및 XAML을 구문 분석할 때 컬렉션 속성이 채워지는 방법에 대한 자세한 내용은 XAML 구문 가이드를 참조하세요.
Children 속성의 값을 유지하는 컬렉션 형식은 UIElementCollection 클래스입니다. UIElementCollection은 UIElement 을 필수 항목 유형으로 사용하는 강력한 형식의 컬렉션입니다. UIElement 는 수백 개의 실제 UI 요소 형식에서 상속되는 기본 형식이므로 여기서 형식 적용은 의도적으로 느슨합니다. 그러나 패널의 직접적인 자식으로 Brush 를 가질 수 없으며, 이는 일반적으로 UI에 표시되며 레이아웃에 참여할 것으로 예상되는 요소들만 패널의 자식 요소로 찾을 수 있다는 점을 의미합니다.
XAML 정의에 의해, 일반적으로 사용자 지정 패널은 Children 속성 as-is특성을 사용해 모든 UIElement 자식 요소를 허용합니다. 고급 시나리오에서는 레이아웃 재정의에서 컬렉션을 반복할 때 자식 요소의 추가 형식 검사를 지원할 수 있습니다.
오버라이드에서 Children 컬렉션을 반복하는 것 외에도, 패널 논리도 Children.Count의 영향을 받을 수 있습니다. 원하는 크기 및 개별 항목의 다른 특성보다는 적어도 부분적으로는 항목 수에 따라 공간을 할당하는 논리가 있을 수 있습니다.
레이아웃 메서드 재정의
기본 모델은 레이아웃 재정의 메서드(MeasureOverride 및 ArrangeOverride)를 사용할 때, 모든 자식 요소를 순환하면서 각 자식 요소의 특정 레이아웃 메서드를 호출해야 한다는 것입니다. 첫 번째 레이아웃 주기는 XAML 레이아웃 시스템이 루트 창의 시각적 요소를 설정할 때 시작됩니다. 각 부모는 자식에 대해 레이아웃을 호출하기 때문에 레이아웃 메서드 호출을 레이아웃의 일부로 간주되는 가능한 모든 UI 요소로 전파합니다. XAML 레이아웃에서는 측정 후 정렬이라는 두 단계가 있습니다.
기본 Panel 클래스에서는 MeasureOverride 및 ArrangeOverride에 대한 기본 제공 레이아웃 메서드 동작이 제공되지 않습니다. 자식 항목은 XAML 시각적 트리의 일부로 자동으로 렌더링되지 않습니다. Children에서 찾은 각 항목에 대해, MeasureOverride와 ArrangeOverride 구현 내의 레이아웃 패스를 통해 레이아웃 메서드를 호출하여 레이아웃 프로세스에 항목이 인식되도록 해야 합니다.
고유한 상속이 없는 한 레이아웃 재정의에서 기본 구현을 호출할 이유가 없습니다. 레이아웃 동작에 대한 기본 메서드(있는 경우)는 항상 실행되며, 재정의에서 기본 구현을 호출하지 않아도 기본 동작은 발생합니다.
레이아웃 논리가 측정을 진행하는 동안, 각 자식 요소에서 Measure 메서드를 호출하여 원하는 크기를 요청합니다. Measure 메서드를 호출하면 DesiredSize 속성의 값이 설정됩니다. MeasureOverride 반환 값은 패널 자체에 대한 원하는 크기입니다.
정렬 패스 중에 자식 요소의 위치와 크기가 x-y 공간에서 결정되고, 레이아웃 구성은 렌더링을 위해 준비됩니다. 코드는 각 자식 요소에 대해 Arrange를 호출하여 Children에 포함된 자식 요소가 레이아웃에 속함을 레이아웃 시스템이 감지할 수 있도록 해야 합니다. Arrange 호출은 컴퍼지션 및 렌더링의 전조입니다. 렌더링을 위해 컴퍼지션이 제출될 때 해당 요소가 어디로 가는지 레이아웃 시스템에 알릴 수 있습니다.
많은 속성과 값은 런타임에 레이아웃 논리가 작동하는 방식에 기여합니다. 레이아웃 프로세스에 대해 생각하는 방법은 자식이 없는 요소(일반적으로 UI에서 가장 깊이 중첩된 요소)가 먼저 측정을 완료할 수 있는 요소라는 것입니다. 그들은 원하는 크기에 영향을 주는 자식 요소에 대한 종속성이 없습니다. 그들만의 원하는 크기가 있을 수 있으며, 이는 레이아웃이 실제로 이루어질 때까지 크기에 대한 제안입니다. 그런 다음, 측정 과정은 루트 요소가 측정되고 모든 측정이 완료될 수 있는 시점까지 시각적 트리를 따라 올라갑니다.
후보 레이아웃은 현재 앱 창 내에 있어야 합니다. 그렇지 않으면 UI의 일부가 잘립니다. 패널은 종종 클리핑 논리가 결정되는 위치입니다. 패널 논리는 MeasureOverride 구현 내에서 사용할 수 있는 크기를 결정할 수 있으며, 자식에게 크기 제한을 적용하고 자식들 간에 공간을 나누어 모든 것을 가능한 한 잘 맞도록 해야 할 수도 있습니다. 레이아웃의 결과는 이상적으로 레이아웃의 모든 부분의 다양한 속성을 사용하지만 여전히 앱 창에 맞는 것입니다. 이를 위해서는 패널의 레이아웃 논리에 적합한 구현과 해당 패널을 사용하여 UI를 빌드하는 모든 앱 코드의 신중한 UI 디자인이 모두 필요합니다. 전체 UI 디자인에 앱에 맞출 수 있는 것보다 더 많은 자식 요소가 포함된다면, 어떤 패널 디자인도 좋아 보이지 않을 것입니다.
레이아웃 시스템이 작동하도록 하는 주요 부분은 FrameworkElement를 기반으로 하는 모든 요소가 컨테이너 내에서 자식으로 동작할 때 이미 고유한 행동을 가지고 있다는 점입니다. 예를 들어, 레이아웃 동작을 알리거나 레이아웃을 작동시키기 위해 필요한 FrameworkElement 응용 프로그램 인터페이스(API) 몇 가지가 있습니다. 여기에는 다음이 포함됩니다.
- 바람직한 크기
(사실상 속성)UIElement - 실제 높이 및 실제 너비
- 높이 및 너비
- 여백
- 레이아웃업데이트 이벤트
- 수평 정렬 및
수직 정렬 - ArrangeOverride 및 MeasureOverride 메서드
- 정렬 및 Measure 메서드: 요소 수준 레이아웃 작업을 처리하는 FrameworkElement 수준에서 정의된 네이티브 구현이 있습니다.
측정 재정의
MeasureOverride 메서드는 반환 값을 가지고 있으며, 이 값은 부모 레이아웃이 패널에서 Measure 메서드를 호출할 때, 레이아웃 시스템에서 패널 자체의 시작 DesiredSize로 사용됩니다. 메서드 내의 논리 선택은 반환되는 항목만큼 중요하며 논리는 반환되는 값에 영향을 주는 경우가 많습니다.
모든 MeasureOverride 구현은 Children을 순회하고 각 자식 요소에서 Measure 메서드를 호출해야 합니다. Measure 메서드를 호출하면 DesiredSize 속성의 값이 설정됩니다. 이것은 패널 자체에 필요한 공간을 비롯하여, 그 공간이 각 요소 사이에 어떻게 분배되는지 또는 특정 자식 요소에 맞춰 어떻게 크기가 결정되는지를 알 수 있도록 합니다.
MeasureOverride 메서드의 기본적인 기본 구조는 다음과 같습니다.
protected override Size MeasureOverride(Size availableSize)
{
Size returnSize; //TODO might return availableSize, might do something else
//loop through each Child, call Measure on each
foreach (UIElement child in Children)
{
child.Measure(new Size()); // TODO determine how much space the panel allots for this child, that's what you pass to Measure
Size childDesiredSize = child.DesiredSize; //TODO determine how the returned Size is influenced by each child's DesiredSize
//TODO, logic if passed-in Size and net DesiredSize are different, does that matter?
}
return returnSize;
}
요소들은 레이아웃이 준비될 때쯤 자연스러운 크기를 가지고 있는 경우가 많습니다. 측정값을 통과한 후 DesiredSizeMeasure 전달한 availableSize 더 작은 경우 자연 크기를 나타낼 수 있습니다. 자연 크기가 availableSize 보다 클 경우, Measure에서, DesiredSize 는 availableSize로 제한됩니다. 이것이 Measure의 내부 구현이 동작하는 방식이며 레이아웃 재정의는 해당 동작을 고려해야 합니다.
일부 요소는 높이와 너비에 대해 자동 값이 있어 자연스러운 크기가 없습니다. 이러한 요소는 전체 availableSize를 사용합니다. Auto 값은 요소를 즉시 레이아웃 부모가 availableSize를 사용하여 Measure를 호출함으로써 최대 사용 가능한 크기로 조정하는 것을 나타냅니다. 실제로 UI는 항상 어떤 측정값에 맞춰 크기가 조정됩니다 (최상위 창일 경우에도 마찬가지입니다). 결국, 측정 패스는 모든 자동 값을 부모 제약으로 해결하고, 모든 자동 요소는 실제 측정값을 얻습니다. 레이아웃 완료 후에 ActualWidth 및 ActualHeight를 확인하여 이러한 실제 측정값을 확인할 수 있습니다.
패널이 콘텐츠의 측정값에 맞게 크기를 조정하려고 시도할 수 있음을 나타내기 위해 하나 이상의 무한 차원이 있는 Measure 크기를 전달하는 것은 합법적입니다. 측정되는 각 자식 요소는 자연 크기를 사용하여 DesiredSize 값을 설정합니다. 그런 다음 정렬 패스 중에 패널은 일반적으로 해당 크기를 사용하여 정렬합니다.
TextBlock 같은 텍스트 요소에는 텍스트 문자열 및 텍스트 속성에 따라 계산된 ActualWidth 및 ActualHeight 가 있으며, Height 또는 Width 값이 설정되지 않은 경우에도 이러한 차원은 패널 논리에 따라 준수되어야 합니다. 텍스트가 잘리는 것은 특히 나쁜 UI 경험입니다.
구현에서 원하는 크기 측정값을 사용하지 않더라도, 각 자식 요소에서 Measure 메서드를 호출하는 것이 좋습니다. 이는 Measure가 호출될 때 트리거되는 내부 및 네이티브 동작이 있기 때문입니다. 요소가 레이아웃에 참여하려면 각 자식 요소에 대해 측정 패스 동안 Measure가 호출되고 정렬 패스 동안 Arrange 메서드가 호출되어야 합니다. 이러한 메서드를 호출하면 개체에 대한 내부 플래그가 설정되고 시스템의 레이아웃 논리가 시각적 트리를 빌드하고 UI를 렌더링할 때 필요한 값(예: DesiredSize 속성)이 채워집니다.
MeasureOverride 반환 값은 Children의 각 자식 요소에 대해 Measure가 호출될 때, 패널의 논리가 DesiredSize 또는 기타 크기 고려 사항을 해석한 결과에 기반합니다. 자식의 DesiredSize 값을 처리하는 방법과 MeasureOverride 반환 값에서 이를 활용하는 방식은 여러분의 고유한 논리 해석에 달려 있습니다. MeasureOverride 입력은 종종 패널의 부모가 제안하는 고정된 사용 가능한 크기이기 때문에, 보통은 값을 수정 없이 합산하지 않습니다. 해당 크기를 초과하면 패널 자체가 잘려질 수 있습니다. 일반적으로 자식의 총 크기를 패널의 사용 가능한 크기와 비교하고 필요한 경우 조정합니다.
팁 및 지침
- 이상적으로, 사용자 지정 패널은 UI 구성 요소의 첫 번째 실제 시각적 개체가 되는 데 적합해야 하며, 이는 Page, UserControl 또는 XAML 페이지 루트인 다른 요소 바로 아래 수준일 수 있습니다. MeasureOverride 구현에서는 값을 검사하지 않고, 입력 Size을(를) 관례적으로 반환하지 마세요. 반환 Size에 무한대 값을 포함하면 런타임 레이아웃 논리에서 예외가 발생할 수 있습니다. 무한대 값은 스크롤할 수 있으므로 최대 높이가 없는 주 앱 창에서 가져올 수 있습니다. 스크롤 가능한 다른 콘텐츠도 동일한 동작을 가질 수 있습니다.
- MeasureOverride 구현의 또 다른 일반적인 실수는 새 기본 크기을 반환하는 것입니다(높이 및 너비 값은 0임). 해당 값으로 시작할 수 있으며 패널에서 자식을 렌더링하지 말아야 한다고 판단하는 경우 올바른 값일 수도 있습니다. 그러나 기본 크기 때문에 패널의 크기가 호스트에 의해 제대로 조정되지 않습니다. UI에 공간을 요청하지 않으므로, 공간을 차지하지 않아 렌더링되지 않습니다. 그렇지 않으면 모든 패널 코드가 잘 작동할 수 있지만 높이가 0, 너비가 0인 경우 패널 또는 콘텐츠가 표시되지 않습니다.
- 재정의 내에서는 자식 요소를 FrameworkElement로 캐스팅하고, 특히 ActualWidth 및 ActualHeight와 같이 레이아웃 결과로 계산된 속성을 사용하려는 유혹을 피하십시오. 대부분의 일반적인 시나리오에서는 자식의 DesiredSize 값에 대한 논리를 기반으로 할 수 있으며 자식 요소의 Height 또는 Width 관련 속성이 필요하지 않습니다. 요소의 형식을 알고 이미지 파일의 자연스러운 크기와 같은 추가 정보가 있는 특수한 경우 레이아웃 시스템에 의해 적극적으로 변경되는 값이 아니므로 요소의 특수 정보를 사용할 수 있습니다. 레이아웃 계산 속성을 레이아웃 논리의 일부로 포함하면 의도하지 않은 레이아웃 루프를 정의할 위험이 크게 증가합니다. 이러한 루프는 유효한 레이아웃을 만들 수 없는 조건을 발생시키고 루프를 복구할 수 없는 경우 시스템에서 LayoutCycleException 을 throw할 수 있습니다.
- 패널은 일반적으로 사용 가능한 공간을 여러 자식 요소 간에 나누지만, 공간을 분할하는 정확한 방법은 다양합니다. 예를 들어, Grid는 RowDefinition 및 ColumnDefinition 값을 사용하여 별 크기 조정 및 픽셀 값을 모두 지원하는 Grid 셀로 공간을 분할하는 레이아웃 논리를 구현합니다. 픽셀 값인 경우, 각 자식에 사용할 수 있는 크기는 이미 알려져 있으므로 그리드 스타일 Measure의 입력 크기로 전달됩니다.
- 패널 자체는 항목 간의 안쪽 여백을 위한 예약된 공간을 추가할 수 있습니다. 이렇게 하려면, 측정값을 Margin 또는 Padding 속성과 구별되는 속성으로 노출해야 합니다.
- 요소는 이전 레이아웃 패스를 기반으로 ActualWidth 및 ActualHeight 속성에 대한 값을 가질 수 있습니다. 값이 변경되면 실행할 특별한 논리가 있는 경우 앱 UI 코드에서 LayoutUpdated에 대한 처리기를 요소에 배치할 수 있지만, 패널 논리는 일반적으로 이벤트 처리를 통해 변경 내용을 확인할 필요가 없습니다. 레이아웃 관련 속성이 값을 변경하면 레이아웃 시스템은 이미 언제 레이아웃을 다시 실행할지 결정하며, 해당 상황에서는 패널의 MeasureOverride 또는 ArrangeOverride가 자동으로 호출됩니다.
배열재정의
ArrangeOverride 메서드에는 패널 자체를 렌더링할 때 레이아웃 시스템에서 사용하는 Size 반환 값이 있으며, Arrange 메서드가 부모 레이아웃에 의해 패널에서 호출될 때 사용됩니다. 일반적으로 입력 finalSize와 ArrangeOverride에 의해 반환된 Size는 동일합니다. 그렇지 않다면, 패널이 레이아웃 내 다른 참가자들이 사용할 수 있다고 주장하는 크기와 다른 크기로 자신을 변경하려고 시도한다는 의미입니다. 최종 크기는 이전에 패널 코드를 통해 레이아웃의 측정값 전달을 실행한 것을 기반으로 했기 때문에 다른 크기를 반환하는 것이 일반적이지 않습니다. 즉, 측정값 논리를 의도적으로 무시한다는 의미입니다.
무한대 구성 요소가 있는 Size를 반환하지 마세요. 내부 레이아웃에서 이 크기을 사용하려고 하면 예외가 발생합니다.
모든 ArrangeOverride 구현은 Children을 반복 처리하고, 각 자식 요소에서 Arrange 메서드를 호출해야 합니다. Measure마찬가지로 배열에는 반환 값이 없습니다. Measure와 달리, 계산된 속성은 결과로 설정되지 않습니다. 하지만 해당 요소는 일반적으로 LayoutUpdated 이벤트를 발생시킵니다.
ArrangeOverride 메서드의 기본적인 기본 구조는 다음과 같습니다.
protected override Size ArrangeOverride(Size finalSize)
{
//loop through each Child, call Arrange on each
foreach (UIElement child in Children)
{
Point anchorPoint = new Point(); //TODO more logic for topleft corner placement in your panel
// for this child, and based on finalSize or other internal state of your panel
child.Arrange(new Rect(anchorPoint, child.DesiredSize)); //OR, set a different Size
}
return finalSize; //OR, return a different Size, but that's rare
}
레이아웃의 정렬 패스는 측정 패스 없이도 발생할 수 있습니다. 그러나 이 문제는 레이아웃 시스템에서 이전 측정값에 영향을 줄 수 있는 속성이 변경되지 않았다고 판단한 경우에만 발생합니다. 예를 들어 맞춤이 변경되더라도, 그로 인해 DesiredSize가 변경되지 않으므로 해당 특정 요소를 다시 측정할 필요가 없습니다. 반면, ActualHeight가 레이아웃의 모든 요소에서 변경될 경우 새 측정 패스가 필요합니다. 레이아웃 시스템은 자동으로 실제 측정값 변경 내용을 감지하고 측정값 패스를 다시 호출한 다음 다른 정렬 패스를 실행합니다.
정렬 입력은 Rect 값을 사용합니다. Rect을 생성하는 가장 일반적인 방법은 포인트 입력과 사이즈 입력이 있는 생성자를 사용하는 것입니다. 지점 요소에 대한 경계 상자의 왼쪽 위 모서리를 배치해야 하는 지점입니다. 크기은 특정 요소를 렌더링하는 데 사용되는 치수입니다. 해당 요소에 대해 DesiredSize를 이 Size 값으로 자주 사용하는 이유는 레이아웃에 관련된 모든 요소의 DesiredSize를 설정하는 것이 레이아웃 측정 과정의 목적이기 때문입니다. 측정 패스는 레이아웃 시스템이 정렬 패스를 진행할 때 요소가 배치되는 방식을 최적화할 수 있도록, 반복적인 절차를 통해 요소의 전체 크기를 결정합니다.
일반적으로 ArrangeOverride 구현 간에 차이가 나는 것은 패널이 각 자식을 배열하는 방법의 Point 구성 요소를 결정하는 논리입니다. Canvas와 같은 절대 위치 지정 패널은 Canvas.Left 및 Canvas.Top 값을 통해 각 요소에서 가져오는 명시적 배치 정보를 사용합니다. Grid와 같은 공간 분할 패널에는 사용 가능한 공간을 셀로 분할하는 수학 연산이 있고 각 셀에는 콘텐츠를 배치하고 정렬해야 하는 위치에 대한 x-y 값이 있습니다. StackPanel 같은 적응형 패널이 콘텐츠의 방향에 맞춰 확장될 수 있습니다.
레이아웃의 요소에는 이미 직접 제어할 수 있는 것과 Arrange에 전달하는 것을 넘어서는 추가적인 위치 지정 요인이 있습니다. 이것은 모든 FrameworkElement 파생 형식에 공통적이며, 텍스트 요소와 같은 다른 형식에 의해 확장되는 Arrange의 내부 네이티브 구현에서 유래합니다. 예를 들어, 요소에는 여백과 정렬이 있을 수 있으며, 일부는 안쪽 여백을 가질 수 있습니다. 이러한 속성은 종종 상호 작용합니다. 자세한 내용은 정렬, 여백 및 안쪽 여백참조하세요.
패널 및 컨트롤
대신 사용자 지정 컨트롤로 빌드해야 하는 사용자 지정 패널에 기능을 배치하지 않습니다. 패널의 역할은 자동 레이아웃 기능의 일환으로 그 안에 있는 자식 요소 콘텐츠를 표시하는 것입니다. 패널은 장식을 콘텐츠에 추가하거나( 테두리 가 표시되는 요소 주위에 테두리를 추가하는 방법과 유사) 안쪽 여백과 같은 다른 레이아웃 관련 조정을 수행할 수 있습니다. 그러나 시각적 트리 출력을 보고하고 자식의 정보를 사용하는 것 이상의 수준으로 확장하지 말아야 합니다.
사용자가 액세스할 수 있는 상호 작용이 있는 경우 패널이 아닌 사용자 지정 컨트롤을 작성해야 합니다. 예를 들어 스크롤 막대, 엄지 손가락 등은 대화형 컨트롤 부분이기 때문에 클리핑을 방지하는 것이 목표인 경우에도 패널에서 표시되는 콘텐츠에 스크롤 뷰포트를 추가하면 안 됩니다. (콘텐츠에는 결국 스크롤 막대가 있을 수 있지만 자식의 논리에 맡기어야 합니다. 스크롤을 레이아웃 작업으로 추가하여 강제 적용하지 마세요.) 컨트롤을 만들고 컨트롤의 시각적 트리에서 중요한 역할을 하는 사용자 지정 패널을 작성하여 해당 컨트롤의 콘텐츠를 표시할 수도 있습니다. 그러나 컨트롤과 패널은 고유한 코드 개체여야 합니다.
제어판과 패널을 구분하는 것이 중요한 이유 중 하나는 Microsoft UI 자동화 및 접근성 때문입니다. 패널은 논리적 동작이 아닌 시각적 레이아웃 동작을 제공합니다. UI 요소가 시각적으로 표시되는 방식은 일반적으로 접근성 시나리오에 중요한 UI의 측면이 아닙니다. 접근성은 UI를 이해하는 데 논리적으로 중요한 앱 부분을 노출하는 것입니다. 상호 작용이 필요한 경우 컨트롤은 UI 자동화 인프라에 상호 작용 가능성을 노출해야 합니다. 자세한 내용은 사용자 지정 자동화 피어을 참조하세요.
기타 레이아웃 API
레이아웃 시스템의 일부이지만 패널에서 선언되지 않은 다른 API가 있습니다. 패널 구현 또는 패널을 사용하는 사용자 지정 컨트롤에서 이러한 개체를 사용할 수 있습니다.
- UpdateLayout, InvalidateMeasure및 InvalidateArrange 레이아웃 패스를 시작하는 메서드입니다. InvalidateArrange는 측정 패스를 트리거하지 않을 수 있지만, 다른 두 가지는 트리거됩니다. 레이아웃 루프를 발생시킬 것이 거의 확실하기 때문에 레이아웃 메서드 재정의 내에서 이러한 메서드를 호출하지 마세요. 제어 코드는 보통 다른 경우와 마찬가지로 그것들을 호출할 필요가 없습니다. 레이아웃의 대부분의 측면은 Width 등과 같은 프레임워크 정의 레이아웃 속성의 변경 내용을 검색하여 자동으로 트리거됩니다.
- LayoutUpdated는 요소 레이아웃의 일부 측면이 변경되는 경우 발생하는 이벤트입니다. 이는 패널에만 국한되지 않습니다. 이벤트는 FrameworkElement에 의해 정의됩니다.
- SizeChanged 은 레이아웃 패스가 완료된 후에만 발생하는 이벤트이며, 이 이벤트로 인해 ActualHeight 또는 ActualWidth 이 변경되었음을 나타냅니다. 이는 또 다른 FrameworkElement 이벤트입니다. LayoutUpdated가 발생하는 경우가 있지만 SizeChanged는 발생하지 않는 경우가 있습니다. 예를 들어 내부 내용이 다시 정렬될 수 있지만 요소의 크기는 변경되지 않았습니다.
관련 항목
참조
개념
Windows developer