Share via


XAML 사용자 지정 패널 개요

패널은 XAML(Extensible Application Markup Language) 레이아웃 시스템이 실행되고 앱 UI가 렌더링될 때 포함된 자식 요소에 대한 레이아웃 동작을 제공하는 개체입니다.

중요 API: Panel, ArrangeOverride,MeasureOverride

Panel 클래스에서 사용자 지정 클래스를 파생시켜 XAML 레이아웃에 대한 사용자 지정 패널을 정의할 수 있습니다. MeasureOverrideArrangeOverride 메서드를 재정의하고 자식 요소를 측정하고 정렬하는 논리를 제공하여 패널에 대한 동작을 제공합니다.

Panel 기본 클래스

사용자 지정 패널 클래스를 정의하려면 Panel 클래스에서 직접 파생하거나 Grid 또는 StackPanel과 같이 봉인되지 않은 실제 패널 클래스 중 하나에서 파생할 수 있습니다.을 이미 레이아웃 동작이 있는 패널의 기존 레이아웃 논리를 해결하는 것이 어려울 수 있으므로 Panel에서 파생는 것이 더 쉽습니다. 또한 동작이 있는 패널에는 패널의 레이아웃 기능과 관련이 없는 기존 속성이 있을 수 있습니다.

Panel에서 사용자 지정 패널은 다음 API를 상속합니다.

  • Children 속성입니다.
  • Background, ChildrenTransitionsIsItemsHost속성 및 종속성 속성 식별자입니다. 이러한 속성은 가상이 아니므로 일반적으로 재정의하거나 대체할 수 없습니다. 일반적으로 사용자 지정 패널 시나리오에는 이러한 속성이 필요하지 않으며 값을 읽는 데에도 필요하지 않습니다.
  • 레이아웃은 MeasureOverrideArrangeOverride메서드를 재정의합니다. 이는 원래 FrameworkElement에 의해 정의되었습니다. 기본 Panel 클래스는 재정의하지 않지만 Grid와 같은 실제 패널에는 네이티브 코드로 구현되고 시스템에서 실행되는 재정의 구현이 있습니다. ArrangeOverrideMeasureOverride에 대한 새로운(또는 추가적인) 구현을 제공하는 것은 사용자 지정 패널을 정의하는 데 필요한 많은 노력입니다.
  • 높이, 가시성 같은 FrameworkElement, UIElementDependencyObject 등 다른 모든 API 레이아웃 재정의에서 이러한 속성의 값을 참조하는 경우도 있지만 가상이 아니므로 일반적으로 재정의하거나 대체하지 않습니다.

여기서는 사용자 지정 패널이 레이아웃에서 어떻게 작동할 수 있고 작동해야 하는지에 대한 모든 가능성을 고려할 수 있도록 XAML 레이아웃 개념을 설명하는 데 중점을 둡니다. 사용자 지정 패널 구현 예제를 보려면 사용자 지정 패널 예제인 BoxPanel을 참조하세요.

Children 속성입니다.

Children 속성은 Panel에서 파생된 모든 클래스가 Children 속성을 컬렉션에 포함된 자식 요소를 저장할 위치로 사용하기 때문에 사용자 지정 패널과 관련이 있습니다. ChildrenPanel 클래스의 XAML 콘텐츠 속성으로 지정되며 Panel에서 파생된 모든 클래스는 XAML 콘텐츠 속성 동작을 상속할 수 있습니다. 속성이 XAML 콘텐츠 속성으로 지정되면 마크업에서 해당 속성을 지정할 때 속성 요소를 생략할 수 있으며 해당 값이 즉각적인 마크업 자식("콘텐츠")으로 설정된다는 의미입니다. 예를 들어 새 동작을 정의하지 않는 Panel에서 CustomPanel이라는 클래스를 파생하는 경우에도 이 태그를 사용할 수 있습니다.

<local:CustomPanel>
  <Button Name="button1"/>
  <Button Name="button2"/>
</local:CustomPanel>

XAML 파서가 이 태그를 읽는 경우 Children은 모든 Panel 파생 형식에 대한 XAML 콘텐츠 속성으로 알려져 있으므로 파서는 Children속성의 UIElementCollection 값에 두 개의 Button 요소를 추가합니다. XAML 콘텐츠 속성은 UI 정의에 대한 XAML 태그에서 간소화된 부모-자식 관계를 용이하게 합니다. XAML 콘텐츠 속성 및 XAML을 구문 분석할 때 컬렉션 속성이 채워지는 방법에 대한 자세한 내용은 XAML 구문 가이드를 참조하세요.

Children 속성의 값을 기본 컬렉션 형식은 UIElementCollection 클래스입니다. UIElementCollectionUIElement를 적용된 항목 유형으로 사용하는 강력한 형식의 컬렉션입니다. UIElement는 수백 개의 실제 UI 요소 형식에서 상속되는 기본 형식이므로 여기서는 형식 적용이 의도적으로 느슨합니다. 그러나 Panel의 직접 자식으로 Brush를 사용할 수 없도록 강제하며 일반적으로 UI에 표시되고 레이아웃에 참여해야 하는 요소만 Panel에서 자식 요소로 찾을 수 있음을 의미합니다.

일반적으로 사용자 지정 패널은 Children 속성의 특성을 있는 그대로 사용하여 XAML 정의에 의해 모든 UIElement 자식 요소를 허용합니다. 고급 시나리오에서는 레이아웃 재정의에서 컬렉션을 반복할 때 자식 요소의 추가 형식 검사 지원할 수 있습니다.

재정의에서 Children 컬렉션을 반복하는 것 외에도 패널 논리의 영향을 Children.Count에서 받을 수 있습니다. 원하는 크기와 개별 항목의 다른 특성이 아닌 항목 수에 따라 부분적으로 공간을 할당하는 로직이 있을 수 있습니다.

레이아웃 메서드 재정의

레이아웃 재정의 메서드(MeasureOverrideArrangeOverride)의 기본 모델은 모든 자식을 반복하고 각 자식 요소의 특정 레이아웃 메서드를 호출해야 한다는 것입니다. 첫 번째 레이아웃 주기는 XAML 레이아웃 시스템에서 루트 창에 대한 시각적 개체를 설정하면 시작됩니다. 각 부모가 자식에게 레이아웃을 호출하기 때문에 레이아웃의 일부가 될 수 있는 모든 UI 요소에 레이아웃 메서드 호출이 전파됩니다. XAML 레이아웃에는 측정값, 정렬의 두 단계가 있습니다.

기본 Panel 클래스에서 MeasureOverrideArrangeOverride에 대한 기본 제공 레이아웃 메서드 동작을 가져올 수 없습니다. Children의 항목은 XAML 시각적 트리의 일부로 자동으로 렌더링되지 않습니다. MeasureOverrideArrangeOverride 구현 내의 레이아웃 패스를 통해 Children에서 찾은 각 항목에 대해 레이아웃 메서드를 호출하여 항목을 레이아웃 프로세스에 알려야 합니다.

고유한 상속이 없는 한 레이아웃 재정의에서 기본 구현을 호출할 이유가 없습니다. 레이아웃 동작에 대한 네이티브 메서드(있는 경우)는 관계없이 실행되며, 재정의에서 기본 구현을 호출하지 않으면 네이티브 동작이 발생하지 않습니다.

측정값을 전달하는 동안 레이아웃 논리는 해당 자식 요소에 대해 Measure 메서드를 호출하여 각 자식 요소를 원하는 크기로 쿼리합니다. Measure 메서드를 호출하면 DesiredSize 속성의 값이 설정됩니다. MeasureOverride 반환 값은 패널 자체에 대해 원하는 크기입니다.

정렬 패스 중에 자식 요소의 위치와 크기는 x-y 공간에서 결정되며 레이아웃 컴퍼지션은 렌더링을 위해 준비됩니다. 레이아웃 시스템에서 요소가 레이아웃에 속하는 것을 감지하도록 코드는 Children의 각 자식 요소에 대해 Arrange를 호출해야 합니다. Arrange 호출은 컴퍼지션 및 렌더링의 전조입니다. 렌더링을 위해 컴퍼지션이 제출될 때 해당 요소가 어디로 가는지 레이아웃 시스템에 알릴 수 있습니다.

많은 속성과 값은 런타임에 레이아웃 논리가 작동하는 방식에 영향을 줍니다. 레이아웃 프로세스를 생각하는 한 가지 방법은 자식이 없는 요소(일반적으로 UI에서 가장 깊게 중첩된 요소)가 먼저 측정을 완료할 수 있는 요소라는 것입니다. 원하는 크기에 영향을 주는 자식 요소에 대한 종속성이 없습니다. 원하는 크기가 있을 수 있으며 레이아웃이 실제로 발생할 때까지 크기 제안입니다. 그런 다음 루트 요소에 측정값이 있고 모든 측정값이 완료될 때까지 측정값 패스가 시각적 트리를 계속 올라갑니다.

후보 레이아웃은 현재 앱 창 내에 있어야 합니다. 그렇지 않으면 UI의 일부가 잘립니다. 패널은 종종 클리핑 논리가 결정되는 위치입니다. 패널 논리는 MeasureOverride 구현 내에서 사용할 수 있는 크기를 결정할 수 있으며, 크기 제한을 자식에게 강요하고 모든 것이 최대한 맞도록 자식끼리 공간을 나눠야 할 수도 있습니다. 레이아웃의 결과는 레이아웃의 모든 부분의 다양한 속성을 사용하면서도 앱 창에 잘 맞는 것이 이상적입니다. 이를 위해서는 패널의 레이아웃 로직을 잘 구현하는 것은 물론, 해당 패널을 사용하여 UI를 구축하는 앱 코드의 신중한 UI 디자인도 필요합니다. 전체 UI 디자인에 앱에 들어갈 수 있는 것보다 더 많은 자식 요소가 포함되어 있으면 패널 디자인이 잘 보이지 않습니다.

레이아웃 시스템이 작동하게 만드는 많은 부분은 FrameworkElement를 기반으로 하는 모든 요소가 컨테이너에서 자식 역할을 할 때 고유한 고유한 동작을 이미 가지고 있다는 것입니다. 예를 들어 레이아웃 동작을 알리거나 레이아웃을 작동하는 데 필요한 FrameworkElement의 여러 API가 있습니다. 여기에는 다음이 포함됩니다.

MeasureOverride

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;
}

요소의 크기는 레이아웃 준비가 될 때까지 자연스럽게 크기가 조정되는 경우가 많습니다. 측정값을 통과한 후에는 Measure에 대해 전달한 availableSize가 더 작은 경우 DesiredSize가 자연 크기임을 나타낼 수 있습니다. 자연 크기가 Measure에 대해 전달한 availableSize보다 크면 DesiredSizeavailableSize로 제한됩니다. 이것이 Measure의 내부 구현이 동작하는 방식이며 레이아웃 재정의는 해당 동작을 고려해야 합니다.

일부 요소에는 HeightWidth에 대한 Auto 값이 있으므로 자연 크기가 없습니다. 이러한 요소는 전체 availableSize를 사용합니다. Auto 값이 나타내는 값이므로 즉시 레이아웃 부모가 Measure with availableSize를 호출하여 통신하는 최대 사용 가능한 크기로 요소 크기를 조정합니다. 실제로 UI의 크기가 조정되는 측정값은 항상 있습니다(최상위 창인 경우에도). 결국 측정 단계는 모든 Auto 값을 부모 제약 조건으로 확인하고 모든 Auto 값 요소는 실제 측정값을 가져옵니다(레이아웃이 완료된 후 ActualWidthActualHeight를 확인하여 얻을 수 있음).

패널이 콘텐츠의 측정값에 맞게 크기를 조정하려고 시도할 수 있음을 나타내기 위해 하나 이상의 무한 차원이 있는 Measure에 크기를 전달하는 것은 합법적입니다. 측정되는 각 자식 요소는 자연 크기를 사용하여 DesiredSize 값을 설정합니다. 그런 다음 정렬 패스 중에 패널은 일반적으로 해당 크기를 사용하여 정렬합니다.

TextBlock과 같은 텍스트 요소에는 Height 또는 Width 값이 설정되지 않은 경우에도 텍스트 문자열 및 텍스트 속성에 따라 계산된 ActualWidthActualHeight가 있으며 이러한 차원은 패널 논리에 따라 존중되어야 합니다. 텍스트를 클리핑하는 것은 특히 나쁜 UI 환경입니다.

구현에서 원하는 크기 측정값을 사용하지 않더라도 Measure가 호출되는 내부 및 네이티브 동작이 있기 때문에 각 자식 요소에서 Measure 메서드를 호출하는 것이 가장 좋습니다. 요소가 레이아웃에 참여하려면 각 자식 요소에 측정값 전달 중에 Measure가 호출되고 정렬 패스 중에 Arrange 메서드가 호출되어야 합니다. 이러한 메서드를 호출하면 개체에 대한 내부 플래그가 설정되고 시스템의 레이아웃 논리가 시각적 트리를 빌드하고 UI를 렌더링할 때 필요한 값(예: DesiredSize 속성)이 채워집니다.

MeasureOverride 반환 값은 Measure가 호출될 때 Children의 각 자식 요소에 대해 DesiredSize 또는 기타 크기 고려 사항을 해석하는 패널의 논리를 기반으로 합니다. 자식의 DesiredSize 값으로 수행할 작업 및 MeasureOverride 반환 값에서 값을 사용하는 방법은 사용자 고유의 논리 해석에 달려 있습니다. MeasureOverride의 입력은 종종 패널의 부모가 제안하는 고정된 사용 가능한 크기이기 때문에 일반적으로 수정 없이 값을 추가하지 않습니다. 해당 크기를 초과하면 패널 자체가 잘려질 수 있습니다. 일반적으로 자식의 총 크기를 패널의 사용 가능한 크기와 비교하고 필요한 경우 조정합니다.

팁 및 지침

  • 이상적으로 사용자 지정 패널은 Page, UserControl 또는 XAML 페이지 루트인 다른 요소 바로 아래의 수준에서 UI 컴퍼지션의 첫 번째 실제 시각적 개체가 되는 데 적합해야 합니다. MeasureOverride 구현에서 값을 검사하지 않고 입력 Size를 정기적으로 반환하지 마세요. 반환 Size무한대 값이 있는 경우 런타임 레이아웃 논리에서 예외를 throw할 수 있습니다. 무한대 값은 스크롤할 수 있으므로 최대 높이가 없는 기본 앱 창에서 가져올 수 있습니다. 스크롤 가능한 다른 콘텐츠도 동일한 동작을 가질 수 있습니다.
  • MeasureOverride 구현의 또 다른 일반적인 실수는 새 기본 Size(높이 및 너비 값은 0)를 반환하는 것입니다. 해당 값으로 시작할 수 있으며 패널에서 자식을 렌더링하지 말아야 한다고 판단하는 경우 올바른 값일 수도 있습니다. 그러나 기본 크기로 인해 패널의 크기가 호스트에서 올바르게 조정되지 않습니다. UI에 공백을 요청하지 않으므로 공백을 가져오지 않고 렌더링되지 않습니다. 그렇지 않으면 모든 패널 코드가 잘 작동할 수 있지만 높이가 0, 너비가 0인 경우 패널 또는 콘텐츠가 표시되지 않습니다.
  • 재정의 내에서 자식 요소를 FrameworkElement로 캐스팅하고 레이아웃, 특히 ActualWidthActualHeightt의 결과로 계산된 속성을 사용하려는 유혹을 피합니다. 대부분의 일반적인 시나리오에서는 자식의 DesiredSize 값에 대한 논리를 기반으로 할 수 있으며 자식 요소의 Height 또는 Width관련 속성은 필요하지 않습니다. 요소의 형식을 알고 이미지 파일의 자연스러운 크기와 같은 추가 정보가 있는 특수한 경우 레이아웃 시스템에 의해 적극적으로 변경되는 값이 아니므로 요소의 특수 정보를 사용할 수 있습니다. 레이아웃 계산 속성을 레이아웃 논리의 일부로 포함하면 의도하지 않은 레이아웃 루프를 정의할 위험이 크게 증가합니다. 이러한 루프는 유효한 레이아웃을 만들 수 없는 조건을 발생시키고 루프를 복구할 수 없는 경우 시스템에서 LayoutCycleException을 throw할 수 있습니다.
  • 패널은 일반적으로 사용 가능한 공간을 여러 자식 요소 간에 나누지만, 정확히 공간 분할 방법은 다양합니다. 예를 들어 GridRowDefinitionColumnDefinition 값을 사용하여 공간을 Grid 셀로 나누는 레이아웃 논리를 구현하여 별 크기 조정과 픽셀 값을 모두 지원합니다. 픽셀 값인 경우 각 자식에 사용할 수 있는 크기는 이미 알려져 있으므로 그리드 스타일 측정값에 대한 입력 크기로 전달됩니다.
  • 패널 자체는 항목 간의 안쪽 여백을 위한 예약된 공간을 도입할 수 있습니다. 이렇게 하면 측정값을 Margin 또는 Padding 속성과 구별되는 속성으로 노출해야 합니다.
  • 요소는 이전 레이아웃 패스를 기반으로 ActualWidthActualHeight 속성에 대한 값을 가질 수 있습니다. 값이 변경되면 실행할 특별한 논리가 있는 경우 앱 UI 코드에서 LayoutUpdated에 대한 처리기를 요소에 배치할 수 있지만 일반적으로 패널 논리는 이벤트 처리와 함께 변경 내용을 검사 필요가 없습니다. 레이아웃 관련 속성 값이 변경되고 적절한 상황에서 패널의 MeasureOverride 또는 ArrangeOverride가 자동으로 호출되므로 레이아웃 시스템이 레이아웃을 다시 실행할 시기를 이미 결정합니다.

ArrangeOverride

ArrangeOverride 메서드에는 레이아웃에서 부모에 의해 패널에서 Arrange메서드를 호출할 때 패널 자체를 렌더링할 때 레이아웃 시스템에서 사용하는 Size 반환 값이 있습니다. 일반적으로 입력 finalSizeArrangeOverride가 반환된 Size는 동일합니다. 그렇지 않은 경우 패널이 레이아웃 클레임의 다른 참가자를 사용할 수 있는 것과 다른 크기를 만들려고 시도한다는 의미입니다. 최종 크기는 이전에 패널 코드를 통해 레이아웃의 측정값 전달을 실행한 것을 기반으로 했기 때문에 다른 크기를 반환하는 것이 일반적이지 않습니다. 즉, 측정값 논리를 의도적으로 무시한다는 의미입니다.

무한대 구성 요소가 있는 Size를 반환하지 마세요. 이러한 크기를 사용하려고 하면 내부 레이아웃에서 예외가 발생합니다.

모든 ArrangeOverride 구현은 Children 요소를 반복하고 각 자식 요소에 대해 Arrange 메서드를 호출해야 합니다. Measure와 마찬가지로 Arrange에는 반환 값이 없습니다. 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가 레이아웃의 모든 요소에서 변경되는 경우 새 측정값 전달이 필요합니다. 레이아웃 시스템은 자동으로 실제 측정값 변경 내용을 감지하고 측정값 패스를 다시 호출한 다음 다른 정렬 패스를 실행합니다.

Arrange에 대한 입력은 Rect 값을 사용합니다. 이 Rect를 생성하는 가장 일반적인 방법은 Point 입력 및 Size 입력이 있는 생성자를 사용하는 것입니다. Point은 요소에 대한 경계 상자의 왼쪽 위 모서리를 배치해야 하는 지점입니다. The Size는 특정 요소를 렌더링하는 데 사용되는 차원입니다. 레이아웃에 관련된 모든 요소에 대해 DesiredSize를 설정하는 것이 레이아웃 측정값의 목적이었기 때문에 해당 요소에 대해 DesiredSize를 이 Size 값으로 사용하는 경우가 많습니다. (측정값 패스는 레이아웃 시스템이 정렬 패스에 도착하면 요소가 배치되는 방식을 최적화할 수 있도록 반복적인 방식으로 요소의 전체 크기 조정을 결정합니다.)

일반적으로 ArrangeOverride 구현 간에는 패널이 각 자식 정렬 방법의 Point 구성 요소를 결정하는 논리가 달라집니다. Canvas와 같은 절대 위치 지정 패널은 Canvas.LeftCanvas.Top 값을 통해 각 요소에서 가져오는 명시적 배치 정보를 사용합니다. Grid와 같은 공간 분할 패널에는 사용 가능한 공간을 셀로 분할하는 수학 연산이 있고 각 셀에는 콘텐츠를 배치하고 정렬해야 하는 위치에 대한 x-y 값이 있습니다. StackPanel과 같은 적응형 패널은 방향 차원의 콘텐츠에 맞게 자체적으로 확장될 수 있습니다.

직접 제어하고 Arrange에 전달하는 것 이상으로 레이아웃의 요소에 대한 추가 위치 지정 영향이 여전히 있습니다. 이는 모든 FrameworkElement 파생 형식에 공통되고 텍스트 요소와 같은 일부 다른 형식에 의해 보강되는 Arrange의 내부 네이티브 구현에서 비롯됩니다. 예를 들어 요소에는 여백과 맞춤이 있을 수 있으며 일부는 안쪽 여백을 가질 수 있습니다. 이러한 속성은 종종 상호 작용합니다. 자세한 내용은 맞춤, 여백 및 패딩을 참조하세요.

패널 및 컨트롤

대신 사용자 지정 컨트롤로 빌드해야 하는 사용자 지정 패널에 기능을 배치하지 않습니다. 패널의 역할은 자동으로 발생하는 레이아웃 함수로서 그 안에 존재하는 자식 요소 콘텐츠를 표시하는 것입니다. 패널은 장식을 콘텐츠에 추가하거나(테두리가 표시되는 요소 주위에 Border를 추가하는 방법과 유사) 안쪽 여백과 같은 다른 레이아웃 관련 조정을 수행할 수 있습니다. 그러나 시각적 트리 출력을 보고하고 자식의 정보를 사용하는 것 이상으로 확장할 때는 이 작업을 수행해야 합니다.

사용자가 액세스할 수 있는 상호 작용이 있는 경우 패널이 아닌 사용자 지정 컨트롤을 작성해야 합니다. 예를 들어 스크롤 막대, 엄지손가락 등은 대화형 제어 부분이므로 클리핑을 방지하려는 목적이 있더라도 패널이 표시하는 콘텐츠에 스크롤 뷰포트를 추가해서는 안 됩니다. (콘텐츠에는 결국 스크롤 막대가 있을 수 있지만 자식의 논리에 맡기어야 합니다. 스크롤을 레이아웃 작업으로 추가하여 강제 적용하지 마세요.) 컨트롤을 만들고 컨트롤의 시각적 트리에서 중요한 역할을 하는 사용자 지정 패널을 작성하여 해당 컨트롤의 콘텐츠를 표시할 수도 있습니다. 그러나 컨트롤과 패널은 고유한 코드 개체여야 합니다.

제어판과 패널을 구분하는 것이 중요한 이유 중 하나는 Microsoft UI 자동화 접근성 때문입니다. 패널은 논리적 동작이 아닌 시각적 레이아웃 동작을 제공합니다. UI 요소가 시각적으로 표시되는 방식은 일반적으로 접근성 시나리오에 중요한 UI의 측면이 아닙니다. 접근성이란 앱에서 UI를 이해하는 데 논리적으로 중요한 부분을 노출하는 것입니다. 상호 작용이 필요한 경우 컨트롤은 UI 자동화 인프라에 상호 작용 가능성을 노출해야 합니다. 자세한 내용은 사용자 지정 자동화 피어를 참조하세요.

기타 레이아웃 API

레이아웃 시스템의 일부이지만 Panel.에서 선언되지 않은 다른 API가 있습니다. 패널 구현 또는 패널을 사용하는 사용자 지정 컨트롤에서 이러한 개체를 사용할 수 있습니다.

  • UpdateLayout, InvalidateMeasureInvalidateArrange는 레이아웃 단계를 시작하는 메서드입니다. InvalidateArrange는 측정값 통과를 트리거하지 않을 수 있지만 다른 두 가지는 트리거합니다. 레이아웃 루프를 발생시킬 것이 거의 확실하기 때문에 레이아웃 메서드 재정의 내에서 이러한 메서드를 호출하지 마세요. 제어 코드는 일반적으로 호출할 필요가 없습니다. 레이아웃의 대부분의 측면은 Width 등과 같은 프레임워크 정의 레이아웃 속성의 변경 내용을 검색하여 자동으로 트리거됩니다.
  • LayoutUpdated는 요소 레이아웃의 일부 측면이 변경된 경우에 발생하는 이벤트입니다. 이는 패널에만 국한되지 않습니다. 이벤트는 FrameworkElement에 의해 정의됩니다.
  • SizeChanged는 레이아웃 단계가 완료된 후에만 발생하는 이벤트이며, 그 결과로 ActualHeight 또는 ActualWidth가 변경되었음을 나타냅니다. 이는 또 다른 FrameworkElement 이벤트입니다. LayoutUpdated가 발생하지만 SizeChanged가 발생하지 않는 경우가 있습니다. 예를 들어 내부 내용이 다시 정렬될 수 있지만 요소의 크기는 변경되지 않았습니다.

참조

개념