Ich habe ein Listenfeld mit vielen Elementen, deren Wiedergabe teuer ist. Das VirtualizingStackPanel kümmert sich jedoch darum, indem nur die sichtbaren Elemente gerendert werden. Ich möchte die Steuerungsvorlage für ScrollViewer außer Kraft setzen, da die Standardvorlage ein graues Rechteck zwischen der horizontalen und vertikalen Bildlaufleiste aufweist. Ich habe nur die von Microsoft (ScrollViewer ControlTemplate Example), die nicht das Problem mit dem grauen Rechteck haben, zur Verfügung gestellt.VirtualizationStackPanel funktioniert nicht mehr beim Überschreiben der Standardsteuerelementvorlage für ScrollViewer
Diese Steuerungstemplate deaktiviert jedoch die Virtualisierung, indem sie dem VirtualizingStackPanel endlose Höhe gibt. Das bedeutet, dass das VirtualizingStackPanel alle Elemente rendert, da es alle Elemente für sichtbar hält.
In der folgenden Demo-Code zeige ich 10000 Elemente in einer Listbox. Ich verifiziere das Problem, indem ich es mit dem ScrollViewer-Stil und ohne es vergleiche. Damit läuft das Demo sehr langsam, die Größenänderung dauert viele Sekunden. Ohne den Stil ist es sehr schnell. I-Ausgang einige Informationen über den VirtualizingStackPanel meinen Punkt zu beweisen:
Ohne den Scroll Stil (den Stil in den XAML Kommentar out):
Viewportheight: 8
ExtentHeight: 10000
Actual: 245
IsVirtualizing: Wahr
VirtualizationMode: Standard
Mit dem Scroll Stil:
Viewportheight: 0
ExtentHeight: 0
Actual: 272766,666666707
IsVirtualizing: Wahre
VirtualizationMode: Standard
Jede Idee, wie eine Steuer Vorlage für einen Scroll zu schreiben, die nicht Chaos mit Virtualisierung?
XAML:
<Window x:Class="VirtualTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style x:Key="{x:Type ScrollViewer}" TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollContentPresenter Grid.Row="0" Grid.Column="0" />
<ScrollBar
Name="PART_VerticalScrollBar"
Grid.Row="0" Grid.Column="1"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1" Grid.Column="0"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox
ItemsSource="{Binding Numbers}"
ScrollViewer.ScrollChanged="ListBox_ScrollChanged"
Background="Orange">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="2" Margin="5">
<TextBlock Text="{Binding .}" Width="400"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
-Code hinter:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace VirtualTest
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = this;
}
public IEnumerable<double> Numbers
{
get
{
for (int i = 0; i < 10000; i++)
{
yield return i;
}
}
}
private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ListBox listBox = sender as ListBox;
VirtualizingStackPanel virtualizingStackPanel = FindVirtualizingStackPanel(listBox);
Debug.WriteLine("ViewportHeight: " + virtualizingStackPanel.ViewportHeight);
Debug.WriteLine("ExtentHeight: " + virtualizingStackPanel.ExtentHeight);
Debug.WriteLine("ActualHeight: " + virtualizingStackPanel.ActualHeight);
Debug.WriteLine("IsVirtualizing: " + VirtualizingStackPanel.GetIsVirtualizing(virtualizingStackPanel));
Debug.WriteLine("VirtualizationMode: " + VirtualizingStackPanel.GetVirtualizationMode(virtualizingStackPanel));
}
private VirtualizingStackPanel FindVirtualizingStackPanel(Visual visual)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
Visual child = VisualTreeHelper.GetChild(visual, i) as Visual;
if (child != null)
{
if (child is VirtualizingStackPanel)
{
return child as VirtualizingStackPanel;
}
VirtualizingStackPanel found = FindVirtualizingStackPanel(child);
if (found != null)
{
return found;
}
}
}
return null;
}
}
}
Danke, das Stil hat Virtualisierung arbeiten. Sie setzen den Rechteck-Füllpinsel tatsächlich auf SystemColors.ControlBrushKey, warum nicht einfach transparent machen? Was in meinem Stil fehlte, war in der Definition von ScrollContentPresenter: CanContentScroll = "{TemplateBinding CanContentScroll}". Wenn ich hinzufügen, dass die Virtualisierung für mich wieder funktioniert. Vielen Dank. –