【问题标题】:WPF Flow LayoutWPF 流布局
【发布时间】:2012-10-02 03:04:37
【问题描述】:

我有一个带有水平 WrapPanel 的 ListBox,用于创建内容网格。 它会产生正确的布局,但它真的很慢,有超过一百个左右的项目。

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

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

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

【问题讨论】:

    标签: wpf layout listbox itemscontrol flowlayout


    【解决方案1】:

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

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

    1- WrapPanels 可以向两个方向增长,而 StackPanels 只能增长 垂直或水平。并且,增长方向 垂直于面板的方向取决于项目的大小 在面板的方向上,所以不可能 换行到新的行/列,除非最后所有项目的大小 行/列是已知的,但如果两个方向 面板正在被虚拟化(因为它不基于像素 绩效改进的衡量标准)。

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

    开发此面板时采用了以下方案:

    1- 小组的范围永远无法确定。相反,数量 使用以下方法在每个 MeasureOverride 之后估计部分 表达式:'numberofitems/averageitemspersection'。由于平均 每个部分的项目数在每次滚动后更新, 面板的范围是动态的。如果项目,范围将是静态的 面板方向的大小是固定的。

    2- items section/sectionindex 只能按顺序计算, 因此,如果您正在查看第一个项目并跳转到一个部分 绕过一个或多个未实现的部分,面板将使用 估计知道哪个项目是第一个可见的,这将是 如果您返回已实现的部分并返回,则更正 依次。例如:如果面板知道项目 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

    【讨论】:

    • 我接受这是正确的答案,因为它似乎是唯一的选择。
    【解决方案2】:

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

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

       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);
    
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      • 2011-07-21
      • 1970-01-01
      • 2011-12-14
      • 2013-02-17
      • 2010-11-19
      • 2011-11-17
      相关资源
      最近更新 更多