Frage

Ich habe eine ItemsControl eine Liste von Daten enthalten, dass ich möchte, virtualisieren jedoch VirtualizingStackPanel.IsVirtualizing="True" scheint nicht mit einem ItemsControl zu arbeiten.

Ist das wirklich der Fall ist, oder gibt es eine andere Art und Weise, dies zu tun, dass ich bin mir nicht bewusst?

Um zu testen, habe ich den folgenden Code-Block wurde mit:

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

Wenn ich die ItemsControl zu einem ListBox ändern, kann ich sehen, dass das Initialized Ereignis läuft nur ein paar Mal (die großen Margen sind nur so habe ich nur durch ein paar Aufzeichnungen gehen), aber als ItemsControl jedes Element bekommt initialisiert.

Ich habe versucht, die ItemsControlPanelTemplate auf einen VirtualizingStackPanel Einstellung, aber das scheint nicht zu helfen.

War es hilfreich?

Lösung

Es gibt tatsächlich viel mehr zu bieten, als nur die ItemsPanelTemplate Verwendung VirtualizingStackPanel. Der Standard ControlTemplate für ItemsControl hat keine ScrollViewer, die der Schlüssel zur Virtualisierung ist. Zusätzlich zu der der Standard-Steuerelementvorlage für ItemsControl (unter Verwendung der Steuervorlage für ListBox als Vorlage) gibt uns die folgenden:

<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, ein großes Werkzeug für das Betrachten Standard-Steuerungsschablonen ist zeigen mir die Vorlage )

Reise Hinweis:

Sie müssen Set ScrollViewer.CanContentScroll="True" finden Sie unter hier warum.

Beachten Sie auch, dass ich legte VirtualizingStackPanel.VirtualizationMode="Recycling". Dies wird die Zahl der Zeiten TextBlock_Initialized reduzieren wird aufgerufen jedoch viele Textblocks auf dem Bildschirm sichtbar sind. Sie können mehr über UI-Virtualisierung lesen Sie hier .

EDIT: Vergessen, das Offensichtliche zu sagen: als eine alternative Lösung, können Sie einfach ItemsControl mit ListBox ersetzen :) Außerdem lesen Sie in dieser Optimierung der Leistung auf MSDN-Seite und bemerke, dass ItemsControl nicht in der ist „Controls das Implementieren Leistungsmerkmale“ Tabelle, weshalb wir bearbeiten müssen die Steuervorlage.

Andere Tipps

Aufbauend auf DavidN Antwort, hier ist ein Stil, den Sie auf einem Itemscontrol verwenden kann es virtualisieren:

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

Ich weiß nicht, wie der Vorschlag, eine List-Box verwenden, da sie die Auswahl von Zeilen ermöglichen, wo Sie müssen nicht es wollen.

Es ist nur, dass der Standard ItemsPanel kein VirtualizingStackPanel ist. Sie müssen es ändern:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top