WPF流程布局



我有一个ListBox,里面有一个水平的WrapPanel来创建一个内容网格。它产生了正确的布局,但它的真的慢,有一百多个项目。

我在谷歌上看到了一些半生不熟的虚拟化WrapPanel的尝试,但似乎都没有做好生产准备。

我是不是错过了一个技巧?如何获得高性能和灵活的(需要在调整大小时回流)面板布局?

(注意:单元格大小固定)。

是的,虚拟化是正确的步骤。WPF不能一次处理中的大量UI项。编写自己的VirtualizingWrapPanel需要大量的WPF经验。WPF没有"现成"的解决方案,所以您要么必须编写它,要么使用其他人的工作。

与提供StackPanel相同功能的VirtualizingStackPanel不同,这并不能完全作为WPF附带的默认WrapPanel,这有一些原因:

1-包裹面板可以向两个方向生长,而堆叠面板只能生长垂直或水平。此外,增长方向与面板方向正交取决于项目的大小在面板方向上,因此不可能换行到新行/列中,除非最后一行上所有项目的大小行/列是已知的,但如果面板正在被虚拟化(因为它是非像素的性能改进的测量)。

2-范围的大小与行/列(节)。在StackPanel上,这不是问题:由于每个部分只允许一个项目,因此范围宽度/高度为项目数。在WrapPanel上,部分的数量取决于高度依赖于项目的大小,并且由于项目的大小不是固定,可以向任何方向变化,无法计算WrapPanel上的节数。

开发该面板时采用了以下解决方案:

1-该小组的范围从未确定。相反在每次测量覆盖后,使用以下公式估计截面表达式:'numberofitems/averageitemspersect'。由于平均每个部分的项目数在每次滚动后更新面板的范围是动态的。如果项目面板方向的大小是固定的。

2-项目部分/部分索引只能按顺序计算,因此,如果您正在查看第一个项目,并跳到绕过一个或多个未实现的部分,面板将使用估计知道哪个项目是第一个可见的,这将是如果你回到一个已实现的部分并返回按顺序。例如:如果面板知道项目12在第1节,小组估计每节10个项目(第0节为第一个),如果跳到第9节,面板将显示第100个项作为第一个可见项(只有在部分1至9每个部分正好有10个项目)。但如果你去返回第1节,依次访问所有部分,直到到达第9部分,则面板将存储所有项目部分因此直到第10节将不再进行进一步的估计。

3-通常允许滚动查看器中的WrapPanel垂直和水平滚动,但由于我只能虚拟化一个方向,这个包装板将只在这个方向上滚动垂直于面板方向。(意思是你不应该设置显式虚拟化面板高度/宽度)。

复制自;http://virtualwrappanel.codeplex.com/

我不明白你所说的固定单元格是什么意思,但如果你有固定的每个项目的宽度/高度,你可以编写比我提供的更好的虚拟化(VirtualWrapPanel)。只需浏览代码并尝试了解发生了什么。

你所说的"不太管用"可能是因为不可能制作出与WrapPanel完全一样的VirtualizingWrapPanel(因为具体的一行项目取决于下一行项目等等),但如果你把它与每个项目都有相同的宽度/高度这一事实结合起来,我相信你可以做得更好。

此外,您可以在这些文章的基础上编写自己的解决方案;

一:http://blogs.msdn.com/dancre/archive/2006/02/06/implementing-a-virtualized-panel-in-wpf-avalon.aspx

二:http://blogs.msdn.com/dancre/archive/2006/02/13/531550.aspx

三:http://blogs.msdn.com/dancre/archive/2006/02/14/532333.aspx

四:http://blogs.msdn.com/dancre/archive/2006/02/16/implementing-a-virtualizingpanel-part-4-the-goods.aspx

如何尝试使用网格并将项目添加到网格中,例如:

(但我没有测试它的性能)

public void InitializeGridAsFourColumns()
{
for (int i = 0; i < 4; i++)
{
_customGrid.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private static int row = -1;
private static int column = 0;

public void AddItem(item)
{
//Add new RowDefinition every 4 items
if (column % 4 == 0)
{
RowDefinition rd = new RowDefinition();
rd.Height = GridLength.Auto;
_customGrid.RowDefinitions.Add(rd);
row++;
}
item.SetValue(Grid.RowProperty, row);
item.SetValue(Grid.ColumnProperty, column % 4);
column++;
_customGrid.Children.Add(item);
}

相关内容

  • 没有找到相关文章

最新更新