ItemsControl'ü sanallaştırmak?


125

ItemsControlSanallaştırmak istediğim bir veri listesi içeren bir listem var , ancak VirtualizingStackPanel.IsVirtualizing="True"bir ItemsControl.

Durum gerçekten bu mu yoksa bunu yapmanın farkında olmadığım başka bir yolu var mı?

Test etmek için aşağıdaki kod bloğunu kullanıyorum:

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

Şunu değiştirirsem ItemsControlbir etmek ListBox, bunu görebiliyorum Initializedetkinlik yalnızca kez bir avuç çalışan bir yandan olarak, (Sadece birkaç kayıtları üzerinden gitmek zorunda sadece çok büyük marjlar vardır) ItemsControlher öğe İlk degeri.

Ben ayarlama denedi ItemsControlPanelTemplatea VirtualizingStackPanelama bu yardım görünmüyor.

Yanıtlar:


219

Sadece yapım çok daha kendisine aslında var ItemsPanelTemplatekullanılmasını VirtualizingStackPanel. Varsayılan ControlTemplateiçin ItemsControlbir yok ScrollViewersanallaştırma anahtarıdır. İçin varsayılan kontrol şablonuna eklemek ItemsControl(şablon ListBoxolarak kontrol şablonunu kullanmak ) bize şunu verir:

<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, varsayılan kontrol şablonlarına bakmak için harika bir araç, Bana Şablonu Göster'dir )

Dikkat edilmesi gerekenler:

Ayarlamalısınız ScrollViewer.CanContentScroll="True", nedenini görmek için buraya bakın .

Ayrıca koyduğuma dikkat edin VirtualizingStackPanel.VirtualizationMode="Recycling". Bu TextBlock_Initialized, ekranda birçok TextBlock görünmesine rağmen çağrılma sayısını azaltacaktır . UI sanallaştırma hakkında daha fazla bilgiyi buradan okuyabilirsiniz .

DÜZENLEME: Açık olanı belirtmeyi unuttum: alternatif bir çözüm olarak, sadece :) ItemsControlile değiştirebilirsiniz ListBoxAyrıca, MSDN sayfasındaki bu Optimizasyon Performansı sayfasına bakın ve ItemsControl"Performans Özelliklerini Uygulayan Kontroller" tablosunda olmadığını fark edin , bu yüzden kontrol şablonunu düzenlememiz gerekiyor.


1
Teşekkür ederim, tam da aradığım şey buydu! Bir liste kutusundan farklı bir seçim davranışı arıyordum ve o zamanlar bir öğe kontrolü ile yapmanın en kolay olacağını düşündüm.
Rachel

Bu öğe kontrolü daha fazla iç içe geçmişse, ona bir yükseklik de vermelisiniz. Aksi takdirde, kaydırma görüntüleyici gösterilmez.
buckley

9
"Ayrıca VirtualizingStackPanel.VirtualizationMode = Recycling koyduğuma dikkat edin". Sağladığınız örnekte olması gerekmiyor mu?
buckley

Sanallaştırma sarma çalışmaları da mı ItemsControliçine ScrollViewerinstread ekleyerek Scrolliçin ControlTemplate?
demo

@DavidN Çözümünüzde sütun başlıklarını nereye veya nasıl koyabilirim?
Özkan

37

DavidN'in cevabına dayanarak, işte onu sanallaştırmak için bir ItemsControl üzerinde kullanabileceğiniz bir stil:

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

Mutlaka istemediğiniz satırların seçimine izin verdikleri için ListBox kullanma önerisinden hoşlanmıyorum.


-3

Sadece varsayılanın ItemsPanelbir VirtualizingStackPanel. Değiştirmeniz gerekiyor:

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

8
Çözüm eksik olduğu için oy veriyorum. Sanallaştırmayı etkinleştirmek için şablonda bir kaydırma görüntüleyici kullanmanız gerekir.
Saraf Talukder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.