2010-05-06 5 views
103

ItemsControl에는 가상화하고 싶은 데이터 목록이 포함되어 있지만 VirtualizingStackPanel.IsVirtualizing="True"ItemsControl과 작동하지 않는 것으로 보입니다.ItemsControl 가상화?

이 문제가 실제로 발생 했나요? 아니면 인식하지 못하고있는 다른 방법이 있습니까? 나는 ListBoxItemsControl을 변경하면 나는 Initialized 이벤트는 배의 줌 (거대한 마진이 실행되는 것을 볼 수 있습니다,

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

:

내가 다음 코드 블록을 사용하고 테스트하려면 그냥 그래서 몇 가지 레코드를 통과해야), ItemsControl 모든 항목이 초기화되면서.

ItemsControlPanelTemplateVirtualizingStackPanel으로 설정하려고했지만 도움이되지 않습니다.

답변

178

. ItemsControl의 기본값 인 ControlTemplate에는 가상화의 핵심 인 ScrollViewer이 없습니다. (템플릿으로 ListBox에 대한 컨트롤 템플릿을 사용하여) ItemsControl에 대한 기본 컨트롤 템플릿에 추가하면 다음과 같은 우리에게 제공합니다

<ItemsControl 
    VirtualizingStackPanel.IsVirtualizing="True" 
    ScrollViewer.CanContentScroll="True" 
    ItemsSource="{Binding Path=AccountViews.Tables[0]}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <TextBlock 
       Initialized="TextBlock_Initialized" 
       Text="{Binding Path=Name}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.Template> 
     <ControlTemplate> 
     <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> 
    </ItemsControl.Template> 
</ItemsControl> 

(BTW, 기본 컨트롤 템플릿에서 찾고위한 훌륭한 도구가 Show Me The Template입니다)

주의 사항 :

ScrollViewer.CanContentScroll="True"을 입력해야합니다. 그 이유는 here입니다.

또한 VirtualizingStackPanel.VirtualizationMode="Recycling"을 넣었습니다. 이렇게하면 TextBlock_Initialized이 호출되어 많은 TextBlocks가 화면에 표시되는 횟수가 줄어 듭니다. UI 가상화 here 에 대한 자세한 내용을 볼 수 있습니다.

편집 : 명백한 상태로 잊어 버렸 : 대체 솔루션으로, 당신은 단지, 또한 ListBox : 와 ItemsControl 교환이 Optimizing Performance on MSDN page을 확인하고 ItemsControl는 "성능 기능을 구현 컨트롤"에없는 것을 알 수 있습니다 테이블 이 때문에 우리는 컨트롤 템플릿을 편집해야합니다.

+1

고마워요, 제가 찾고 있던 바로 그 종류입니다!나는리스트 박스와는 다른 종류의 선택 동작을 찾고 있었고, 아이템 컨트롤을 사용하는 것이 가장 쉽다고 생각했다. – Rachel

+0

ListView도 이에 해당합니다. –

+0

이 itemscontrol이 더 중첩 된 경우 높이를 지정해야합니다. 그렇지 않으면 스크롤 뷰어가 표시되지 않습니다. – buckley

-3

기본값 인 ItemsPanelVirtualizingStackPanel이 아닙니다. 당신은 그것을 변경해야 실제로 훨씬 더 그것에 단지 ItemsPanelTemplate 사용 VirtualizingStackPanel을보다 더있다

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

감사합니다.하지만 이미 시도했지만 작동하지 않았습니다. – Rachel

+6

솔루션이 불완전하기 때문에 투표를 거절합니다. 템플리트에서 scrollviewer를 사용하여 가상화를 활성화해야합니다. –

22

건물 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> 

을 반드시 그것을 원하지 않습니다.