我有一個列表框,其中有很多渲染費用很高的項目。然而,VirtualizingStackPanel僅通過渲染可見項目來處理。我想覆蓋ScrollViewer的控件模板,因爲默認的模板在水平和垂直滾動條之間有灰色矩形。我剛剛複製了微軟提供的那個(ScrollViewer ControlTemplate Example),它沒有灰色的矩形問題。當覆蓋ScrollViewer的默認控制模板時,VirtualizingStackPanel停止工作
但是,此控件模板通過給予VirtualizingStackPanel無窮高度來禁用虛擬化。這意味着VirtualizingStackPanel將渲染所有項目,因爲它認爲所有項目都可見。
在下面的演示代碼中,我在列表框中顯示10000個項目。我通過比較運行ScrollViewer風格和沒有它來驗證問題。隨着演示運行速度非常緩慢,調整大小需要幾秒鐘。沒有風格,它非常快。 I輸出有關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}」。如果我補充說虛擬化開始爲我工作。謝謝。 – 2010-11-19 13:55:00