스크롤 뷰어 컨트롤

한 영역에 모두 표시할 수 없을 정도로 UI 콘텐츠가 너무 많은 경우 스크롤 뷰어 컨트롤을 사용합니다.

스크롤 뷰어를 사용하면 콘텐츠가 뷰포트(표시 영역)의 경계를 넘어 확장될 수 있습니다. 사용자는 마우스 또는 펜 커서를 사용하여 스크롤 뷰어의 스크롤 막대를 조작하거나 터치, 마우스 휠, 키보드 또는 게임 패드를 통해 스크롤 뷰어 표면을 조작하여 이 콘텐츠에 도달합니다.

상황에 따라 스크롤 뷰어의 스크롤 막대가 사용할 수 있는 두 가지 시각화는 다음 그림에서처럼 패닝 표시기(왼쪽)와 기본 스크롤 썸(오른쪽)이 있습니다.

A screenshot that illustrates a panning scrollbar, a 2 pixel wide vertical line at the right edge of the content.

A screenshot that illustrates the standard scrollbar, a 6 pixel wide vertical line with an up arrow button at the top, and a down arrow at the bottom.

Important

WinUI 3에서 사용 가능한 스크롤 뷰어 컨트롤은 두 가지가 있습니다. ScrollViewer 그리고 ScrollView가 그에 해당합니다. 일반적으로 스크롤 뷰어 컨트롤에 대해 말할 때마다 해당 정보는 두 컨트롤에 모두 적용됩니다.

스크롤, 패닝, 그리고 줌

스크롤 뷰어 컨트롤을 사용하여 콘텐츠의 스크롤, 패닝, 및 줌을 허용합니다.

  • 스크롤: 스크롤바 썸을 드래그하거나 마우스의 스크롤 휠을 사용하여 콘텐츠를 가로 세로로 이동하기.
  • 패닝: 터치 또는 펜 입력을 사용하여 콘텐츠를 가로 세로로 이동하기.
  • : 콘텐츠의 크기를 시각적으로 확정 또는 축소하기.

스크롤바는 사용자의 입력 방식을 인식하고, 입력 방식을 활용해 어떤 시각화를 표시할 지 결정합니다.

  • 스크롤 막대를 직접 조작하지 않고 터치 등으로 영역을 스크롤하는 경우 현재 스크롤 위치 표시와 함께 이동 표시기가 나타납니다.
  • 마우스나 펜 커서가 이동 표시기 위로 이동하면 이동 표시기가 기존 스크롤 막대로 변형됩니다. 스크롤 막대 위치 조정 컨트롤을 끌어 스크롤 영역을 조작합니다.

An animation that shows the scroll bar transform from the narrow panning indicator to the traditional thumb when the cursor moves over it.

참고 항목

스크롤 막대는 ScrollViewer 내의 콘텐츠 맨 위에 16px로 오버레이되어 표시됩니다. 훌륭한 UX 디자인을 만들려면 스크롤 막대가 오버레이되어 대화형 콘텐츠가 잘 보이지 않는 경우가 없도록 합니다. 또한 UX가 겹치지 않도록 하려면 뷰포트의 가장자리에 스크롤 막대를 위한 16px 안쪽 여백을 남겨 둡니다.

뷰포트 및 범위

스크롤 뷰어는 해당 functionality를 이해하는 데 중요한 주요 리전 두 가지로 구성됩니다. 숨겨져 있든 표시되든 무관하게 모든 스크롤 가능한 콘텐츠가 포함된 영역을 범위라고 합니다. 콘텐츠가 표시되는 컨트롤의 표시 영역을 뷰포트라고 합니다.

A block of text that extends beyond the viewport, or visible area of the control.

범위 크기와 뷰포트 크기 차이인 스크롤 가능한 height와 width뿐만 아니라 이 리전의 heigh와 width를 가져올 수 있는 다양한 API를 사용할 수 있습니다.

권장 사항

  • 가능하면 가로보다는 세로 스크롤용으로 설계합니다.
  • 하나의 뷰포트 경계(세로 또는 가로)를 넘어 확장되는 콘텐츠 리전에는 1축 패닝을 사용합니다. 뷰포트 양쪽 경계(세로 및 가로)를 넘어 확장되는 콘텐츠 리전에는 2축 패닝을 사용합니다.
  • 항목 뷰, 리스트 뷰, 그리드 뷰, 콤보 상자, 리스트 상자, 텍스트 입력란 및 허브 컨트롤에서 빌트인 스크롤 functionality를 사용합니다. 한 번에 표시할 항목이 너무 많을 때 이러한 컨트롤을 사용하면 사용자가 항목 리스트 위로 가로 또는 세로로 스크롤할 수 있습니다.
  • 예를 들어 사용자가 (화면에 맞게 크기가 조정된 이미지가 아니라) 전체 크기 이미지처럼 더 큰 영역의 주위에서 양방향으로 패닝하고 줌을 할 수 있도록 하려면, 스크롤 뷰어 내에 이미지를 배치합니다.
  • 사용자가 긴 텍스트 구절을 스크롤하는 경우 세로로만 스크롤할 수 있도록 스크롤 뷰어를 구성합니다.
  • 객체 하나만을 포함하려면 스크롤 뷰어를 사용합니다. 하나의 객체가 레이아웃 패널이 될 수 있으며, 이에 따라 객체의 개수만큼 포함할 수 있습니다.
  • ScrollViewer 또는 ListView와 같이 스크롤할 수 있는 뷰에서 UIElement에 대한 포인터 이벤트를 처리해야 하는 경우에는 UIElement.CancelDirectmanipulation을 호출하여 뷰의 요소에 대한 이벤트 조작 지원을 명시적으로 비활성화해야 합니다. 뷰에서 이벤트 조작을 재활성화하려면 UIElement.TryStartDirectManipulation을 호출합니다.

UWP 및 WinUI 2

참고 항목

ScrollView 컨트롤은 WinUI 3에서만 사용할 수 있습니다. UWP 및 WinUI 2의 경우 ScrollViewer 컨트롤을 사용합니다.

Important

이 문서의 정보 및 예제는 Windows 앱 SDKWinUI 3를 사용하는 앱에 최적화되어 있지만 WinUI 2를 사용하는 UWP 앱에도 대체로 적용 가능합니다. 플랫폼별 정보 및 예제는 UWP API 참조를 확인하세요.

이 섹션에는 UWP 또는 WinUI 2 앱에서 컨트롤을 사용하는 데 필요한 정보를 다룹니다.

이 컨트롤용 API는 Windows.UI.Xaml.Controls 네임스페이스에 있습니다.

최신 WinUI 2를 사용하여 모든 컨트롤에 적용되는 최신 스타일과 템플릿을 가져오는 것이 좋습니다. WinUI 2.2 이상에는 둥근 모서리를 사용하는 이 컨트롤의 새 템플릿이 포함되어 있습니다. 자세한 내용은 모서리 반경을 참조하세요.

스크롤 뷰어 만들기

WinUI 3 갤러리 앱에는 대부분의 WinUI 3 컨트롤, 특징, 기능의 대화형 예제가 포함되어 있습니다. Microsoft Store에서 앱을 다운로드하거나 GitHub에서 소스 코드를 가져오세요

스크롤 뷰어 컨트롤은 스크롤 뷰어에서 콘텐츠를 명시적으로 래핑하거나 콘텐츠 컨트롤의 컨트롤 템플릿에 스크롤 뷰어를 배치하여 콘텐츠를 스크롤할 수 있도록 하는 데 사용할 수 있습니다.

컨트롤 템플릿의 스크롤 뷰어

스크롤 뷰어 컨트롤이 다른 컨트롤의 복합 부분으로 있는 것이 일반적입니다. 스크롤 뷰어 파트는 호스트 컨트롤의 레이아웃 공간이 확장된 콘텐츠 크기보다 작게 제한되는 경우에만 스크롤 막대와 함께 뷰포트를 표시합니다.

ItemsView 는 템플릿에 ScrollView 컨트롤을 포함합니다. 그러나 ScrollViewItemsView.ScrollView 속성을 통해 액세스할 수 있습니다.

ListViewGridView 템플릿에는 항상 ScrollViewer이 있습니다. TextBoxRichEditBox 는 템플릿에도 ScrollViewer 을 포함합니다. 빌트인 ScrollViewer 파트의 동작과 속성 일부에 영향을 주기 위해, ScrollViewer 은 스타일에서 설정되고 템플릿 바인딩에서 사용 가능한 XAML 결합속성 여러 개를 정의합니다. 결합속성에 대한 자세한 내용은 결합속성 개요를 참조하세요.

스크롤 가능한 콘텐츠 설정하기

스크롤 뷰어의 뷰포트보다 크면, 스크롤 뷰어 내의 콘텐츠를 스크롤할 수 있게 됩니다.

다음 예제는 RectangleScrollView 컨트롤의 콘텐츠로 설정합니다. 사용자에게는 해당 사각형의 500x400 부분만 보이며 스크롤하여 나머지 부분을 볼 수 있습니다.

<ScrollView Width="500" Height="400">
    <Rectangle Width="1000" Height="800">
        <Rectangle.Fill>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                <GradientStop Color="Yellow" Offset="0.0" />
                <GradientStop Color="Red" Offset="0.25" />
                <GradientStop Color="Blue" Offset="0.75" />
                <GradientStop Color="LimeGreen" Offset="1.0" />
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</ScrollView>

Layout

이전 예제에서 사각형의 크기가 스크롤 뷰어보다 크도록 명시적으로 설정되었습니다. 스크롤 뷰어 콘텐츠가 자연스럽게 증가할 수 있는 경우 해당 콘텐츠(이 범위)가 세로나, 가로나, 양 방향 모두에서 확장되거나 양 방향 모두에서 확장되지 않게끔 스크롤 뷰어를 구성할 수 있습니다.

예를 들어 이 텍스트 블록은 부모 컨테이너가 텍스트 블록을 제한될 때까지 가로로 성장하고, 이후 텍스트를 래핑하고 세로로 커집니다.

<TextBlock Text="{x:Bind someText}" TextWrapping="WrapWholeWords"/>

텍스트 블록이 스크롤 뷰어에 래핑되면 스크롤 뷰어는 가로 세로 방향으로의 성장을 제한합니다.

Vertical 은 콘텐츠가 가로로 제한되지만 뷰포트 범위를 넘어 세로로 커질 수 있으며 사용자가 콘텐츠를 위아래로 스크롤할 수 있음을 의미합니다.

A block of text that extends vertically beyond the viewport, or visible area of the control, with a vertical scroll bar shown.

Horizontal 은 콘텐츠가 세로로 제한되지만 뷰포트 범위를 넘어 세로로 커질 수 있으며 사용자가 콘텐츠를 좌우로 스크롤할 수 있음을 의미합니다.

A block of text that extends horizontally beyond the viewport, or visible area of the control, with a horizontal scroll bar shown.

스크롤 표시 유형

ScrollViewerScrollView 컨트롤은 약간 다른 방법을 통해 콘텐츠의 가로 세로 방향으로의 스크롤을 구성합니다.

  • ScrollViewer 컨트롤에서 VerticalScrollBarVisibilityHorizontalScrollBarVisibility 속성은 스크롤바 표시 여부와 특정 방향으로의 스크롤 가능 여부를 모두 제어합니다. 속성을 Disabled로 설정하면, 사용자 상호 작용을 통한 해당 방향으로의 콘텐츠 스크롤이 불가능합니다.
    • 기본값은 다음과 같습니다. VerticalScrollBarVisibility="Auto", HorizontalScrollBarVisibility="Disabled"
  • ScrollView 컨트롤에서 VerticalScrollBarVisibilityHorizontalScrollBarVisibility 속성은 스크롤바 표시 여부만을 제어합니다.
    • 기본값은 다음과 같습니다. VerticalScrollBarVisibility="Auto", HorizontalScrollBarVisibility="Auto"

이 표에서는 이러한 속성에 대한 표시 옵션을 설명합니다.

설명
자동 뷰포트에서 모든 콘텐츠를 표시할 수 없는 경우에만 스크롤바가 나타납니다.
비활성화 (ScrollViewer만 해당) 뷰포트에서 모든 콘텐츠를 표시할 수 없는 경우에도 스크롤바가 나타나지 않습니다. 사용자 상호 작용을 통한 스크롤이 비활성화됩니다. (프로그래밍 방식으로 스크롤할 수 있습니다.)
숨겨져 있음 뷰포트에서 모든 콘텐츠를 표시할 수 없는 경우에도 스크롤바가 나타나지 않습니다. 스크롤은 계속 활성화 상태로 터치, 키보드 또는 마우스 휠 상호 작용을 통해 가능합니다.
표시 스크롤바는 항상 나타납니다. (현재 UX 디자인에서 스크롤 막대는 뷰포트가 모든 콘텐츠를 표시할 수 없는 한, 마우스 커서가 위에 있을 때만 나타납니다. )

(ScrollViewer는 ScrollBarVisibility 열거형 을 사용합니다. ScrollView는 ScrollingScrollBarVisibility 열거형을 사용합니다.)

Orientation

ScrollView 컨트롤에는 ContentOrientation 속성이 있어 콘텐츠 레이아웃 제어가 가능합니다. 이 속성은 콘텐츠가 명시적으로 제한된 것이 아닐 때 콘텐츠가 증가하는 방법을 결정합니다. 만약 HeightWidth 이 콘텐츠에 명시적으로 설정된 경우, ContentOrientation 은 아무런 영향을 주지 않습니다.

이 표에서는 ContentOrientation 옵션을 제시하여 ScrollView을 처리하는 법을 보여주며 또한 ScrollViewer에 대한 대응 세팅을 제시합니다.

Orientation ScrollView ScrollViewer
Vertical ContentOrientation="Vertical" VerticalScrollBarVisibility="[Auto][Visible][Hidden]"
HorizontalScrollBarVisibility="Disabled"
수평적 크기 조정 ContentOrientation="Horizontal" VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="[Auto][Visible][Hidden]"
모두 ContentOrientation="Both" VerticalScrollBarVisibility="[Auto][Visible][Hidden]"
HorizontalScrollBarVisibility="[Auto][Visible][Hidden]"
None ContentOrientation="None"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"

Vertical 레이아웃

기본적으로 스크롤 뷰어의 콘텐츠 레이아웃(방향)은 세로입니다.

이 예제에서는 ItemsRepeater 가 ScrollView의 Content로 사용됩니다. ItemsRepeater에 대한 UniformGridLayout은 공간이 부족할 때까지(이 예제에서는 500px) 항목을 행에 가로로 배치한 다음 다음 행에 다음 항목을 배치합니다. ItemsRepeater는 사용자가 볼 수 있는 400px보다 크지만 사용자는 콘텐츠를 세로로 스크롤할 수 있습니다.

기본 ContentOrientation 값은 Vertical로 ScrollView에는 변경이 필요하지 않습니다.

<ScrollView Width="500" Height="400">
    <ItemsRepeater ItemsSource="{x:Bind Albums}"
                   ItemTemplate="{StaticResource MyTemplate}">
        <ItemsRepeater.Layout>
            <UniformGridLayout RowSpacing="8" ColumnSpacing="8"/>
        </ItemsRepeater.Layout>
    </ItemsRepeater>
</ScrollView>

Horizontal 레이아웃

이 예제에서 콘텐츠는 StackPanel 로 항목을 가로로 배치하는 것입니다. 스크롤 뷰어 구성이 가로 스크롤을 지원하도록 변경하고 세로 스크롤은 비활성화합니다.

ScrollView'의 ContentOrientation 속성은 Horizontal 로 설정하여 필요한 만큼 콘텐츠가 가로로 증가할 수 있도록 허용합니다.

<ScrollView Width="500" Height="400" ContentOrientation="Horizontal">
    <StackPanel Orientation="Horizontal">
        <Button Width="200" Content="Button 1"/>
        <Button Width="200" Content="Button 2"/>
        <Button Width="200" Content="Button 3"/>
        <Button Width="200" Content="Button 4"/>
        <Button Width="200" Content="Button 5"/>
    </StackPanel>
</ScrollView>

프로그래밍 방식의 스크롤

스크롤 뷰어의 오프셋 속성은 읽기 전용이지만 프로그래밍 방식으로 스크롤할 수 있는 메서드가 제공됩니다.

ScrollView 컨트롤의 경우, ScrollTo 메서드를 호출하고 스크롤할 가로 세로 방향의 오프셋을 전달합니다. 이 경우 스크롤은 세로 방향이므로 현재 HorizontalOffset 값이 사용됩니다. 위쪽으로 스크롤하려면, 0의 VerticalOffset 을 사용합니다. 아래쪽으로 스크롤하려면, VerticalOffsetScrollableHeight와 동일합니다.

<Button Content="Scroll to top" Click="ScrollTopButton_Click"/>
<Button Content="Scroll to bottom" Click="ScrollBottomButton_Click"/>
<ScrollView x:Name="scrollView" Width="500" Height="400">
    <StackPanel>
        <Button Width="200" Content="Button 1"/>
        <Button Width="200" Content="Button 2"/>
        <Button Width="200" Content="Button 3"/>
        <Button Width="200" Content="Button 4"/>
        <Button Width="200" Content="Button 5"/>
    </StackPanel>
</ScrollView>
private void ScrollTopButton_Click(object sender, RoutedEventArgs e)
{
    scrollView.ScrollTo(
        horizontalOffset: scrollView.HorizontalOffset,
        verticalOffset: 0);
}

private void ScrollBottomButton_Click(object sender, RoutedEventArgs e)
{
    scrollView.ScrollTo(
        horizontalOffset: scrollView.HorizontalOffset,
        verticalOffset: scrollView.ScrollableHeight);
}

또한 ScrollView는 현재 오프셋에서 지정된 델타를 활용해 가로나 세로로 스크롤할 수 있는 ScrollBy 메서드를 제공합니다.

확대/축소

스크롤 뷰어를 사용하여 사용자가 콘텐츠를 시각적으로 줌인과 줌아웃할 수 있습니다. 옵티컬 줌 상호 작용은 핀치와 스트레치 제스처(손가락을 멀리 이동하여 줌인하고 더 가까이 이동하여 줌아웃)를 통해 수행되거나 마우스 스콜을 휠을 스크롤하는 동안 Ctrl 키를 눌러 수행됩니다. 줌에 대한 자세한 내용은 옵티컬 줌과 리사이징 섹션을 참조하세요.

사용자 상호 작용에 따라 줌을 활성화하려면 ZoomMode 속성을 Enabled 로 설정하세요(기본적으로 Disabled 입니다.) 이 ZoomMode 속성에 대한 변경 내용은 즉시 적용되며 진행 중인 사용자 상호 작용에 영향을 줄 수 있습니다.

이 예제에서는 보여주는 이미지는 줌을 허용하도록 구성된 뷰어에 래핑되어 있습니다.

<ScrollView Width="500" Height="400"
            ContentOrientation="Both"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.jpg"/>
</ScrollView>

이 경우 이미지는 스크롤 뷰어에 의해 제한되지 않으므로 처음에는 기본 크기로 표시됩니다. 이미지 소스가 뷰포트보다 큰 경우 사용자는 전체 이미지를 보려면 줌아웃해야 합니다. 이는 의도된 동작이 아닐 수 있습니다.

A picture of a mountain zoomed in so far that only blue sky and clouds in the upper left of the picture are visible.

다음 예제에서는 뷰포트에 이미지를 제한하도록 스크롤 뷰어를 구성하는 방법을 보여 줍니다. 이렇게 하면 처음에 로드된 이미지가 줌아웃되고 사용자가 원하는 경우 줌인 및 스크롤할 수 있습니다.

A picture of a mountain zoomed out so that the foreground, mountain, and sky are all visible.

이미지를 ScrollView의 viewport로 제한하려면 ContentOrientation 속성을 None로 설정합니다. 스크롤바 visibility는 해당 제약 조건에 묶여 있지 않으므로 사용자가 줌인할 때 스크롤바가 자동으로 표시됩니다.

<ScrollView Width="500" Height="400"
            ContentOrientation="None"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.jpg"/>
</ScrollView>

줌 배율

사용자가 콘텐츠를 줌할 수 있는 양을 제어하려면 MinZoomFactorMaxZoomFactor 속성을 사용해야 합니다. 이러한 속성은 사용자 상호 작용 및 프로그래밍 방식 줌 모두에 효과적입니다.

  • 기본값은 다음과 같습니다. MinZoomFactor="0.1", MaxZoomFactor="10.0"
<ScrollView Width="500" Height="400"
            ContentOrientation="Both"
            ZoomMode="Enabled" 
            MinZoomFactor="1.0" MaxZoomFactor="8.0">
    <Image Source="Assets/rainier.png"/>
</ScrollView>

프로그래밍 방식 줌

ZoomFactor 속성은 읽기 전용이지만 프로그래밍 방식으로 줌을 할 수 있도록 메서드가 제공됩니다. 일반적으로 스크롤 뷰어를 줌 크기를 제어하는 슬라이더에 연결하거나 줌 수준을 다시 설정하는 버튼을 사용합니다. (줌 슬라이더의 예시를 보려면 WinUI 3 갤러리 앱의 ScrollViewer를 참조하세요.)

ScrollView 컨트롤의 경우 ZoomTo 메서드를 호출하고 새 줌 요소를 첫 번째 매개 변수로 전달합니다.

<Slider Header="Zoom" IsEnabled="True"
        Maximum="{x:Bind scrollControl.MaxZoomFactor, Mode=OneWay}"
        Minimum="{x:Bind scrollControl.MinZoomFactor, Mode=OneWay}"
        StepFrequency="0.1"
        ValueChanged="ZoomSlider_ValueChanged" />
<ScrollView Width="500" Height="400"
            ContentOrientation="None"
            ZoomMode="Enabled">
    <Image Source="Assets/rainier.png"/>
</ScrollView>
private void ZoomSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    if (scrollControl != null)
    {
        scrollControl.ZoomTo(
            zoomFactor: (float)e.NewValue,
            centerPoint: null)
    }
}

또한 ScrollView는 현재 줌 수준에서 지정된 델타로 확대 및 축소할 수 있는 ZoomBy 메서드를 제공합니다.

샘플 코드 가져오기