У меня есть список с большим количеством предметов, которые дорого переносятся. Однако VirtualizingStackPanel позаботится об этом, только визуализируя видимые элементы. Я хочу переопределить шаблон управления для ScrollViewer, поскольку по умолчанию у него серый прямоугольник между горизонтальной и вертикальной полосами прокрутки. Я просто скопировал файл, предоставленный Microsoft (ScrollViewer ControlTemplate Example), который не имеет проблемы с серым прямоугольником.VirtualizingStackPanel перестает работать при переопределении шаблона управления по умолчанию для ScrollViewer
Эта контрольная таблица, однако, отключает виртуализацию, предоставляя бесконечную высоту VirtualizationStackPanel. Это означает, что VirtualizingStackPanel будет отображать все элементы, поскольку он считает, что все элементы видны.
В приведенном ниже демо-коде я показываю 10000 элементов в списке. Я проверяю проблему, сравнивая ее с стилем ScrollViewer и без него. С ним демо работает очень медленно, изменение размера занимает много секунд. Без стиля это очень быстро. Я выход некоторую информацию о VirtualizingStackPanel, чтобы доказать свою точку зрения:
Без стиля ScrollViewer (Закомментируйте стиль в XAML):
ViewportHeight: 8
ExtentHeight: 10000
ActualHeight: 245
IsVirtualizing: Правда
VirtualizationMode: Стандартный
с стиле ScrollViewer:
ViewportHeight: 0
ExtentHeight: 0
ActualHeight: +272766,666666707
IsVirtualizing: Правда
VirtualizationMode: Стандартный
Любая идея, как написать шаблон управления для ScrollViewer, который не беспорядок с виртуализацией?
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>
Код:
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;
}
}
}
Спасибо, что стиль имеет виртуализация работает. Они фактически устанавливают кисть заливки прямоугольника в SystemColors.ControlBrushKey, почему бы просто не сделать ее прозрачной? То, что отсутствовало в моем стиле, было в определении ScrollContentPresenter: CanContentScroll = "{TemplateBinding CanContentScroll}". Если я добавлю, что виртуализация снова начнет работать для меня. Благодарю. –