ItemsControl 가상화?


125

나는 한 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도움이되지 않는 것 같습니다.

답변:


219

실제로 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하는 이유입니다에없는 "성능을 구현하는 것이 제어가 특징"테이블, 컨트롤 템플릿을 편집해야합니다.


1
감사합니다. 바로 제가 찾던 종류입니다! 나는 목록 상자와 다른 종류의 선택 동작을 찾고 있었고 당시에는 항목 컨트롤을 사용하는 것이 가장 쉬울 것이라고 생각했습니다.
Rachel

이 itemscontrol이 더 중첩되면 높이도 제공해야합니다. 그렇지 않으면 scrollviewer가 표시되지 않습니다.
buckley 2014 년

9
"또한 VirtualizingStackPanel.VirtualizationMode = Recycling을 넣었습니다." 제공 한 샘플에 있어야하지 않습니까?
buckley

가상화는 포장 작업도 하는가 ItemsControlScrollViewerinstread가 추가 ScrollControlTemplate?
데모

@DavidN 솔루션에서 열 머리글을 어디에 또는 어떻게 넣을 수 있습니까?
Ozkan 2017

37

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를 사용하라는 제안이 마음에 들지 않습니다. 원치 않는 행을 선택할 수 있기 때문입니다.


-3

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

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

8
해결책이 불완전하기 때문에 나는 그것을 아래로 투표하고 있습니다. 가상화를 활성화하려면 템플릿에서 스크롤 뷰어를 사용해야합니다.
Saraf Talukder 2015-06-02
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.