주요 API들
레이아웃은 UI의 시각적 구조를 정의하는 프로세스입니다. XAML에서 레이아웃을 설명하는 기본 메커니즘은 패널을 통해서입니다. 패널을 통해 UI 요소를 배치하고 정렬할 수 있는 컨테이너 개체입니다. 레이아웃은 CPU 사용량과 메모리 오버헤드 모두에서 XAML 앱의 비용이 많이 드는 부분이 될 수 있습니다. 다음은 XAML 앱의 레이아웃 성능을 개선하기 위해 수행할 수 있는 몇 가지 간단한 단계입니다.
레이아웃 구조 줄이기
레이아웃 성능의 가장 큰 이득은 UI 요소 트리의 계층 구조를 단순화하는 것입니다. 패널은 시각적 트리에 있지만
많은 UI는 패널과 요소의 깊고 복잡한 트리를 생성하는 중첩 패널에 의해 구현됩니다. 패널을 중첩하는 것이 편리하지만 대부분의 경우 더 복잡한 단일 패널을 사용하여 동일한 UI를 달성할 수 있습니다. 단일 패널을 사용하면 성능이 향상됩니다.
레이아웃 구조를 줄이는 경우
레이아웃 구조를 간단한 방식으로 줄이면(예: 최상위 페이지에서 중첩된 패널 하나를 줄이면) 눈에 띄는 효과가 없습니다.
가장 큰 성능 향상은 ListView 또는 GridView같이 UI에서 반복되는 레이아웃 구조를 줄이면 발생합니다. 이러한 ItemsControl 요소들은 여러 번 인스턴스화되는 UI 요소의 하위 트리를 정의하는 DataTemplate을 사용합니다. 앱에서 동일한 하위 트리가 여러 번 중복되는 경우 해당 하위 트리의 성능이 향상되면 앱의 전반적인 성능에 곱한 영향을 줍니다.
예시
다음 UI를 고려합니다.
다음 예제에서는 동일한 UI를 구현하는 세 가지 방법을 보여 줍니다. 각 구현 선택은 화면에서 거의 동일한 픽셀을 생성하지만 구현 세부 정보는 크게 다릅니다.
Option1: 중첩된 StackPanel 요소
이 모델은 가장 간단한 모델이지만 5개의 패널 요소를 사용하므로 상당한 오버헤드가 발생합니다.
<StackPanel>
<TextBlock Text="Options:" />
<StackPanel Orientation="Horizontal">
<CheckBox Content="Power User" />
<CheckBox Content="Admin" Margin="20,0,0,0" />
</StackPanel>
<TextBlock Text="Basic information:" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" Width="75" />
<TextBox Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Email:" Width="75" />
<TextBox Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Password:" Width="75" />
<TextBox Width="200" />
</StackPanel>
<Button Content="Save" />
</StackPanel>
옵션 2: 단일 그리드
Grid는 일부 복잡성을 추가하지만 단일 패널 요소만을 사용합니다.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="Options:" Grid.ColumnSpan="2" />
<CheckBox Content="Power User" Grid.Row="1" Grid.ColumnSpan="2" />
<CheckBox Content="Admin" Margin="150,0,0,0" Grid.Row="1" Grid.ColumnSpan="2" />
<TextBlock Text="Basic information:" Grid.Row="2" Grid.ColumnSpan="2" />
<TextBlock Text="Name:" Width="75" Grid.Row="3" />
<TextBox Width="200" Grid.Row="3" Grid.Column="1" />
<TextBlock Text="Email:" Width="75" Grid.Row="4" />
<TextBox Width="200" Grid.Row="4" Grid.Column="1" />
<TextBlock Text="Password:" Width="75" Grid.Row="5" />
<TextBox Width="200" Grid.Row="5" Grid.Column="1" />
<Button Content="Save" Grid.Row="6" />
</Grid>
옵션 3: 단일 RelativePanel:
이 단일 패널은 중첩된 패널을 사용하는 것보다 약간 더 복잡하지만 Grid보다 쉽게 이해하고 유지 관리할 수 있습니다.
<RelativePanel>
<TextBlock Text="Options:" x:Name="Options" />
<CheckBox Content="Power User" x:Name="PowerUser" RelativePanel.Below="Options" />
<CheckBox Content="Admin" Margin="20,0,0,0"
RelativePanel.RightOf="PowerUser" RelativePanel.Below="Options" />
<TextBlock Text="Basic information:" x:Name="BasicInformation"
RelativePanel.Below="PowerUser" />
<TextBlock Text="Name:" RelativePanel.AlignVerticalCenterWith="NameBox" />
<TextBox Width="200" Margin="75,0,0,0" x:Name="NameBox"
RelativePanel.Below="BasicInformation" />
<TextBlock Text="Email:" RelativePanel.AlignVerticalCenterWith="EmailBox" />
<TextBox Width="200" Margin="75,0,0,0" x:Name="EmailBox"
RelativePanel.Below="NameBox" />
<TextBlock Text="Password:" RelativePanel.AlignVerticalCenterWith="PasswordBox" />
<TextBox Width="200" Margin="75,0,0,0" x:Name="PasswordBox"
RelativePanel.Below="EmailBox" />
<Button Content="Save" RelativePanel.Below="PasswordBox" />
</RelativePanel>
이러한 예제에서와 같이 동일한 UI를 달성하는 방법에는 여러 가지가 있습니다. 성능, 가독성 및 유지 관리를 비롯한 모든 장단 사항을 신중하게 고려하여 선택해야 합니다.
겹치는 UI에 단일 셀 그리드 사용
일반적인 UI 요구 사항은 요소가 서로 겹치는 레이아웃을 갖는 것입니다. 일반적으로 안쪽 여백, 여백, 정렬 및 변환은 요소를 이렇게 배치하는 데 사용됩니다. XAML Grid 컨트롤은 겹치는 요소의 레이아웃 성능을 향상시키기 위해 최적화되어 있습니다.
중요 개선을 보려면 단일 셀 그리드를 사용하세요. RowDefinitions 또는 ColumnDefinitions정의하지 마세요.
예시
<Grid>
<Ellipse Fill="Red" Width="200" Height="200" />
<TextBlock Text="Test"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<Grid Width="200" BorderBrush="Black" BorderThickness="1">
<TextBlock Text="Test1" HorizontalAlignment="Left" />
<TextBlock Text="Test2" HorizontalAlignment="Right" />
</Grid>
패널의 기본 제공 테두리 속성 사용
Grid, StackPanel, RelativePanel및 ContentPresenter 컨트롤에는 XAML에 Border 요소를 추가하지 않고 테두리를 그릴 수 있는 내장된 테두리 속성이 있습니다. 기본 제공 테두리를 지원하는 새 속성에는 BorderBrush, BorderThickness, CornerRadius및 안쪽 여백이 포함됩니다. 이러한 각 항목은 DependencyProperty속성으로, 바인딩 및 애니메이션과 함께 사용할 수 있습니다. 별도의 Border 요소를 완전히 대체하도록 설계되었습니다.
UI에 이러한 패널 주위에 테두리 요소가 있는 경우, 기본 제공 테두리를 대신 사용하여 앱의 레이아웃 구조에서 추가 요소를 절약하세요. 앞에서 설명한 것처럼 이는 특히 반복되는 UI의 경우 상당한 절감이 될 수 있습니다.
예시
<RelativePanel BorderBrush="Red" BorderThickness="2" CornerRadius="10" Padding="12">
<TextBox x:Name="textBox1" RelativePanel.AlignLeftWithPanel="True"/>
<Button Content="Submit" RelativePanel.Below="textBox1"/>
</RelativePanel>
SizeChanged 이벤트를 사용하여 레이아웃 변경에 응답
FrameworkElement 클래스는 레이아웃 변경에 응답하기 위한 두 가지 유사한 이벤트인 LayoutUpdated 및 SizeChanged노출합니다. 레이아웃 중에 요소의 크기가 조정될 때 이러한 이벤트 중 하나를 사용하여 알림을 받을 수 있습니다. 두 이벤트의 의미 체계는 다르며 둘 중에서 선택할 때 중요한 성능 고려 사항이 있습니다.
성능을 높이려면 SizeChanged를 거의 항상 선택하는 것이 올바릅니다. SizeChanged은 직관적인 의미를 가지고 있습니다. 레이아웃 중에 FrameworkElement의 크기가 업데이트될 때 발생합니다.
LayoutUpdated는 레이아웃 중에도 발생하며, 전역 의미 체계를 가집니다. 이는 모든 요소가 업데이트될 때마다 모든 요소에서 발생합니다. 이벤트 처리기에서만 로컬 처리를 수행하는 것이 일반적이며, 이 경우 코드가 필요 이상으로 자주 실행됩니다. 요소가 크기는 그대로이고 위치만 변경되었을 때 이를 알아야 하는 경우에만 LayoutUpdated를 사용하세요 (이는 흔하지 않습니다).
패널 중에서 선택
일반적으로 성능은 개별 패널 중에서 선택할 때 고려 사항이 아닙니다. 이러한 선택은 일반적으로 구현하는 UI에 가장 가까운 레이아웃 동작을 제공하는 패널을 고려하여 결정됩니다. 예를 들어 Grid, StackPanel, 그리고 RelativePanel중에서 선택하는 경우, 구현에 대한 당신의 mental model에 가장 가까운 매핑을 제공하는 패널을 선택해야 합니다.
모든 XAML 패널은 우수한 성능을 위해 최적화되며, 모든 패널은 유사한 UI에 유사한 성능을 제공합니다.