我有一个ItemsControl在a中显示其项目ScrollViewer,并进行虚拟化.我试图将其滚动ScrollViewer到它包含的(屏幕外,因此虚拟化)项目.但是,由于项目是虚拟化的,因此屏幕上并不存在并且没有位置(IIUC).
我已尝试BringIntoView过子元素,但它不会滚动到视图中.我也尝试手动用做它TransformToAncestor,TransformBounds和ScrollToVerticalOffset,但TransformToAncestor不会返回(我猜是因为虚拟化的同时,因为它没有位置,但我没有这方面的证明)和代码它从未执行后.
是否可以滚动到虚拟化的项目ItemsControl?如果是这样,怎么样?
我想使用ItemsControl显示重要的项目列表.
我正在使用ItemsControl的原因是DataTemplate在我正在处理的应用程序中要复杂得多:提供的示例代码仅反映了我的调整问题.
我想要 :
它的大小自动扩展到其父容器(Grid)
<Grid>
<ItemsControl x:Name="My" ItemsSource="{Binding Path=Names}">
<ItemsControl.Template>
<ControlTemplate>
<StackPanel>
<StackPanel>
<TextBlock Text="this is a title" FontSize="15" />
<TextBlock Text="This is a description" />
</StackPanel>
<ScrollViewer CanContentScroll="True" Height="400px">
<VirtualizingStackPanel IsItemsHost="True" />
</ScrollViewer>
</StackPanel>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Run Code Online (Sandbox Code Playgroud)
背后的代码是:
public partial class Page1: Page
{
public List<string> Names { get; set; }
public Page1()
{
InitializeComponent();
Names = new List<string>();
for(int i = 0; i < 10000; i++)
Names.Add("Name : …Run Code Online (Sandbox Code Playgroud) 我使用StackPanel垂直布局几个控件(即标题,子标题,列表框,分隔符,列表框等).
StackPanel是ScrollViewer的子代,以确保其内容始终可滚动.
StackPanel中的一个控件是ListBox.
其ItemsSource是绑定到大型集合的数据,复杂的DataTemplate用于实现每个项目.
不幸的是,我的性能(高CPU /内存)非常糟糕.
我试过了
但是表演没有区别.我猜测StackPanel在测量期间给它的内部儿童无限高度?
当我用其他面板/布局(例如,Grid,DockPanel)替换ScrollViewer和StackPanel并且性能显着提高时,这让我相信瓶颈和解决方案都在虚拟化中.
有什么方法可以改善这个视图的CPU /内存性能吗?

[更新1]
原始示例项目:http://s000.tinyupload.com/index.php?file_id = 29810707815310047536
[更新2]
我尝试重新设置/模板化TreeView/TreeViewItems来提供以下示例.它仍然需要很长时间才能启动/使用相同的高内存.但是一旦加载,滚动感觉比原始样本响应更快.
想知道是否还有其他方法可以进一步改善启动时间/内存使用情况?
重新设计的TreeView项目:http://s000.tinyupload.com/index.php?file_id = 00117351345725628185
[更新2]
pushpraj的解决方案就像一个魅力
我有以下ListBox:
<ScrollViewer>
<!--Spec Definitions-->
<ListBox DataContext="{Binding SpecPackageSpecGroupListViewModel}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ScrollViewer.IsDeferredScrollingEnabled="True"
ItemContainerStyle="{StaticResource SpecPackageSpecGroupListBoxStyle}"
ItemsSource="{Binding SortedChildren}"
Background="Transparent"
BorderThickness="0" SelectionMode="Extended"
Margin="5,5,5,5">
<ListBox.ItemTemplate>
<DataTemplate>
<Controls:SpecPackageSpecGroupControl/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
这个列表框应该容纳〜1000个项目,但是复杂的项目.我希望它能与VirtualizingStackPanel一起使用,所以我将可视化XAML配置设置为:
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
Run Code Online (Sandbox Code Playgroud)
我的问题是我认为它不起作用 - 首先 - 加载~700项需要很长时间,其次,当我在控制构造函数上遇到断点时 - 我可以看到它被调用700次:
public static int Counter = 0;
public SpecPackageSpecGroupControl()
{
InitializeComponent();
Counter++;
if (Counter%100 == 0)
Console.WriteLine("Hi");
}
Run Code Online (Sandbox Code Playgroud)
我在Console.WriteLine("Hi")上断点,我可以看到静态计数器达到了700.
所以基本上是创建UIElements,尽管这是一种虚拟模式.
我误解了虚拟化模式,还是我做错了什么?
因此,如果项目在滚动区域的末尾被剪切/裁剪,那么拥有无铬集合看起来真的很愚蠢.
我想为集合(ItemsControl/ListBox)创建一个虚拟化面板,它只绘制整个项目,而不是项目.例如:
______________
| |
|______________|
______________
| |
|______________|
______________
| |
Run Code Online (Sandbox Code Playgroud)

我不希望显示第三个部分容器,除非有足够的空间显示整个项目/容器.在示例中,由于空间不足,第三个项目被裁剪.
有什么建议?我应该尝试重新发明轮子(构建我自己的VirtualizingWholeItemPanel)吗?
编辑:
微软澄清说,VirtualizingPanel.ScrollUnit根本不打算执行此功能.看来,VirtualizingPanel.ScrollUnit提供一个非常类似的宗旨,以旧CanContentScroll上ScrollViewer.
我知道 DataGrid 支持虚拟化,因此它仅为可见行创建网格单元。但是,这似乎仅在 DataGrid 大小受到限制的情况下才有效。
在我的场景中,DataGrid 放置在滚动查看器内,如下所示
<ScrollViever>
<StackPanel>
<more elements .../>
<DataGrid ... />
<more elements .../>
</StackPanel>
</ScrollViever>
Run Code Online (Sandbox Code Playgroud)
这似乎破坏了虚拟化。在 DataGrid 应显示大量项目的情况下,即使在外部 ScrollViewer 中向下滚动之前,视觉树也会变得非常大。
有什么方法可以防止 DataGrid 预先创建所有单元格,而是在 ScrollViewer 向下滚动时创建它们?
编辑:基本上,托管此内容的页面应该像一个网页,顶部有一些文本,底部有一个大表格和更多文本。整个页面应该滚动,而不是顶部/底部始终可见且仅滚动网格的停靠视图。该设置实现了这一点,但由于一切都是预先创建的而受到影响。
另一个编辑:有没有办法检测数据网格的特定行已滚动到视图中?典型的延迟加载文章使用数据网格的滚动查看器向网格添加更多项目,这在这里不起作用。
这个问题主要针对Windows Phone开发人员,但我想任何XAML技术都适用.
我的VirtualizingStackPanel作品很棒,我可以看到内存使用的改进.但是,我在其中的项目的ListBox高度可变,并且实例化/绑定可能非常复杂.
当滚动速度非常快时,您会在面板赶上时开始看到死空间.在我看来,如果面板能够提前渲染更多项目,则可以解决此问题.
在这一点上,我感觉它只会在最后一个可见项目之后再渲染1或2个项目.有没有办法增加这个数字?可以提前5件物品吗?
如果答案是"否",有没有办法欺骗/破解它?
xaml virtualizingstackpanel windows-phone-7 windows-phone windows-phone-8
我有一个列表框,里面有很多渲染成本很高的项目。然而,VirtualizingStackPanel 通过只渲染可见项来处理这个问题。我想覆盖 ScrollViewer 的控件模板,因为默认的控件模板在水平和垂直滚动条之间有灰色矩形。我只是复制了微软提供的一个(ScrollViewer ControlTemplate Example),它没有灰色矩形问题。
然而,这个控制模板通过给 VirtualizingStackPanel 无限的高度来禁用虚拟化。这意味着 VirtualizingStackPanel 将呈现所有项目,因为它认为所有项目都是可见的。
在下面的演示代码中,我在列表框中显示了 10000 个项目。我通过比较运行它与 ScrollViewer 样式和没有它来验证问题。有了它,演示运行得非常慢,调整大小需要几秒钟。没有样式它非常快。我输出了一些关于 VirtualizingStackPanel 的信息来证明我的观点:
没有 ScrollViewer 样式(注释掉 XAML 中的样式):
ViewportHeight: 8
ExtentHeight: 10000
ActualHeight: 245
IsVirtualizing: True
VirtualizationMode: Standard
使用 ScrollViewer 样式:
ViewportHeight: 0
ExtentHeight: 0
ActualHeight: 272766.666666707
IsVirtualizing: True
VirtualizationMode: Standard
知道如何为不会与虚拟化混淆的 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 …Run Code Online (Sandbox Code Playgroud) 我最近开始探索WPF中的数据和UI虚拟化功能,偶然发现了一些奇怪的东西.
我创建了一个DataGrid"s的Virtualizing启用和一个有1,000,000项的列表填充它.这种方法效果非常好而且速度惊人.
<Grid>
<DataGrid x:Name="employees" VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsContainerVirtualizable="True"
VirtualizingPanel.VirtualizationMode="Recycling"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
但是,当我把它嵌入它下载StackPanel超过一分钟直到我得到OutOfMemoryException.我也设置了相同的VirtualizingPanel属性,StackPanel但它没有帮助.
这种行为是故意还是我错过了一些基本的东西?我如何设法在嵌套控件中支持数据虚拟化?
我有一个ListView用于显示字段列表的wpf; 基于属性值,某些字段可以在运行时折叠.它的工作正常,但ListVIew不会折叠为在运行时折叠的ListViewItem保留的空间.

我能够在Snoop中看到额外的ListViewItems(可见性为折叠),ListView也会向上移动项目,但它不会调整其高度以移除空白区域!
我可以肯定地说,由于VirtualizedStackPanel将ItemsPanel更改为StackPanel解决了这个问题,这种情况正在发生.这是相关的ListViewXAML:
<ListView
x:Class="Wizards.FieldBinderModelListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Margin="0"
VerticalAlignment="Top"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Top"
Background="White"
BorderThickness="0"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Continue"
Padding="1"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectionChanged="ListViewSelectionChanged"
SelectionMode="Single">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<!--Works fine with StackPanel but not with VirtualizingStackPanel
Explicitly added this PanelTemplate to show that it works with
StackPanel;ListView uses VirtualizingStackPanel as default panel
and causes same problem-->
<!--<StackPanel Orientation="Vertical" VerticalAlignment="Top"/>-->
<VirtualizingStackPanel Orientation="Vertical"
VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black" />
</Trigger>
<DataTrigger Binding="{Binding …Run Code Online (Sandbox Code Playgroud) 有人可以告诉我如何在WPF中正确使用VirtualizingStackPanel吗?我在ItemsPanelTemplate中为我的ItemsControl设置了一个VirtualizingStackPanel,并将其设置为我的ItemsHost,但是当我在我的item控件上注册一个CleanUpVirtualizedItem附加事件的监听器时,没有任何反应.我没有看到事件被调用.我也没有看到我的数据模板中的自定义控件上的任何Unloaded事件被调用,这表明我没有实际的虚拟化.任何帮助将非常感激.
我将ItemsControl与VirtualizingStackPanel一起作为项目面板,如下所示:
<ItemsControl Style="{StaticResource ItemsControl}" Name="itemsControl"
Margin="0,100,0,0" HorizontalAlignment="Stretch" Height="80">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
风格如下:
<Style x:Key="ItemsControl" TargetType="ItemsControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
我设置了一个包含100.000个元素作为ItemsSource的集合,并获得了非常好的性能.除了一件事,一切都很好.当我在其中一个文本框中输入文本然后开始滚动时,我发现该文本在整个列表中随处可见!
我理解VirtualizingStackPanel的功能.它会不断加载在滚动时变得可见的元素.我理解它的虚拟化技术的一些方面,但我不知道如何理解这种奇怪的行为.我没能在WPF/Silverlight虚拟化上找到好的文档,所以,请解释一下发生了什么
wpf ×11
itemscontrol ×3
c# ×2
datagrid ×2
scrollviewer ×2
stackpanel ×2
.net ×1
.net-4.0 ×1
.net-4.5 ×1
itemspanel ×1
listbox ×1
listview ×1
scrollview ×1
silverlight ×1
xaml ×1