如果你愿意使用反射来访问VirtualizingStackPanel的私有功能,并将VirtualizingStackPanel的私有属性IsPixelBased设置为true,那么在WPF 4.0中实现平滑滚动的VirtualizingStackPanels就不需要放弃虚拟化。
请注意,在.NET 4.5中,无需使用此技巧,因为您可以将VirtualizingPanel.ScrollUnit设置为"Pixel"。
为了使它真正简单易行,这里是一些代码:
public static class PixelBasedScrollingBehavior
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(PixelBasedScrollingBehavior), new UIPropertyMetadata(false, HandleIsEnabledChanged));
private static void HandleIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var vsp = d as VirtualizingStackPanel;
if (vsp == null)
{
return;
}
var property = typeof(VirtualizingStackPanel).GetProperty("IsPixelBased",
BindingFlags.NonPublic | BindingFlags.Instance);
if (property == null)
{
throw new InvalidOperationException("Pixel-based scrolling behaviour hack no longer works!");
}
if ((bool)e.NewValue == true)
{
property.SetValue(vsp, true, new object[0]);
}
else
{
property.SetValue(vsp, false, new object[0]);
}
}
}
例如,要在 ListBox 上使用它,您可以执行以下操作:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel PixelBasedScrollingBehavior.IsEnabled="True">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>