[wpf] ItemsControl 가상화?

나는 한 ItemsControl하지만, 내가 가상화하고자하는 데이터의 목록을 포함 VirtualizingStackPanel.IsVirtualizing="True"와 함께 작동하지 않습니다 ItemsControl.

이것이 정말로 사실입니까 아니면 내가 알지 못하는 다른 방법이 있습니까?

테스트를 위해 다음 코드 블록을 사용했습니다.

<ItemsControl ItemsSource="{Binding Path=AccountViews.Tables[0]}"
              VirtualizingStackPanel.IsVirtualizing="True">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBlock Initialized="TextBlock_Initialized"
                   Margin="5,50,5,50" Text="{Binding Path=Name}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

나는를 변경하는 경우 ItemsControlA를 ListBox, 나는 것을 볼 수 있습니다 Initialized이벤트는 시간의 소수를 실행하는 그러나로, (나는 몇 레코드를 가야 단지, 그래서 거대한 마진은) ItemsControl모든 항목이 초기화됩니다.

ItemsControlPanelTemplate를 a로 설정하려고했지만 VirtualizingStackPanel도움이되지 않는 것 같습니다.



답변

실제로 ItemsPanelTemplate사용 하는 것보다 훨씬 더 많은 것이 있습니다 VirtualizingStackPanel. 기본 ControlTemplate에 대한 ItemsControl이없는 ScrollViewer가상화의 핵심입니다. ItemsControl( 컨트롤 템플릿을 템플릿으로 사용)에 대한 기본 컨트롤 템플릿에 추가 ListBox하면 다음과 같은 이점이 있습니다.

<ItemsControl ItemsSource="{Binding AccountViews.Tables[0]}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBlock Initialized="TextBlock_Initialized"
                 Text="{Binding Name}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>

  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel IsVirtualizing="True"
                              VirtualizationMode="Recycling" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderThickness="{TemplateBinding BorderThickness}"
              BorderBrush="{TemplateBinding BorderBrush}"
              Background="{TemplateBinding Background}">
        <ScrollViewer CanContentScroll="True"
                      Padding="{TemplateBinding Padding}"
                      Focusable="False">
          <ItemsPresenter />
        </ScrollViewer>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
</ItemsControl>

(BTW, 기본 컨트롤 템플릿을 보기 위한 훌륭한 도구는 Show Me The Template입니다. )

주의 사항 :

설정해야합니다 . 이유 ScrollViewer.CanContentScroll="True"여기 를 참조 하십시오 .

또한 VirtualizingStackPanel.VirtualizationMode="Recycling". 이렇게하면 TextBlock_Initialized호출되는 횟수 가 줄어들지 만 화면에 많은 TextBlock이 표시됩니다. 여기
에서 UI 가상화에 대해 자세히 알아볼 수 있습니다 .

편집 : 명백한 상태로 잊어 버렸 : 대체 솔루션으로, 당신은 단지 대체 할 수 ItemsControl와 함께 ListBox🙂 또한이 체크 아웃 MSDN 페이지에 최적화 성능을 통보 ItemsControl하는 이유입니다에없는 “성능을 구현하는 것이 제어가 특징”테이블, 컨트롤 템플릿을 편집해야합니다.


답변

DavidN의 답변을 바탕으로 ItemsControl에서 가상화 할 수있는 스타일은 다음과 같습니다.

<!--Virtualised ItemsControl-->
<Style x:Key="ItemsControlVirtualizedStyle" TargetType="ItemsControl">
    <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ItemsControl">
                <Border
                    BorderThickness="{TemplateBinding Border.BorderThickness}"
                    Padding="{TemplateBinding Control.Padding}"
                    BorderBrush="{TemplateBinding Border.BorderBrush}"
                    Background="{TemplateBinding Panel.Background}"
                    SnapsToDevicePixels="True"
                >
                    <ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ListBox를 사용하라는 제안이 마음에 들지 않습니다. 원치 않는 행을 선택할 수 있기 때문입니다.


답변

기본값 ItemsPanelVirtualizingStackPanel. 변경해야합니다.

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>


답변