1

コンテンツのグリッドを作成するために、内部に水平の WrapPanel を持つ ListBox があります。正しいレイアウトを生成しますが、アイテムが 100 を超えると非常に遅くなります

Google で WrapPanel を仮想化する中途半端な試みがいくつか見られますが、いずれも本番環境に対応しているようには見えません。

私はトリックを逃していますか?パフォーマンスが高く柔軟な (サイズ変更時にリフローが必要な) パネル レイアウトを取得するにはどうすればよいですか?

(注: セルは固定サイズです)。

4

2 に答える 2

3

はい、仮想化は正しいステップです。WPF は一度に大量の UI 項目を処理できません。独自の VirtualizingWrapPanel を作成するには、WPF でかなりの経験が必要です。WPFには「すぐに使える」ソリューションがないため、それを作成するか、他の誰かの作業を使用する必要があります。

StackPanel と同じ機能を提供する VirtualizingStackPanel とは異なり、これは WPF に付属するデフォルトの WrapPanel として完全には動作しません。これにはいくつかの理由があります。

1- WrapPanel は 2 方向に拡張できますが、StackPanel は垂直方向または水平方向にしか拡張できません。また、パネルの向きに直交する方向の成長は、パネルの向きの方向のアイテムのサイズに依存するため、最後の行/列のすべてのアイテムのサイズが変わらない限り、新しい行/列に折り返すことはできません。列は既知ですが、パネルの 2 つの方向が仮想化されている場合、これは不可能です (パフォーマンス向上のために非ピクセルベースの測定を行うため)。

2-エクステントのサイズは、行/列(セクション)の数と同じです。StackPanel では、これは問題ではありません。セクションごとに 1 つのアイテムしか許可されていないため、エクステントの幅/高さはアイテムの数です。WrapPanel では、セクションの数は項目のサイズに大きく依存します。項目のサイズは固定されておらず、どの方向にも変化する可能性があるため、WrapPanel でセクションの数を計算することはできません。

このパネルの開発時には、次のソリューションが採用されました。

1- パネルの範囲は確実にわかりません。代わりに、「numberofitems/averageitemspersection」という式を使用して、各 MeasureOverride の後にセクション数が推定されます。セクションごとのアイテムの平均数はスクロールのたびに更新されるため、パネルの範囲は動的です。パネルの向きでアイテムのサイズが固定されている場合、範囲は静的になります。

2- アイテム セクション/セクション インデックスは順番にしか計算できないため、最初のアイテムを表示していて、1 つ以上の未実現セクションをバイパスするセクションにジャンプすると、パネルは推定を使用して最初に表示されるアイテムを認識します。これは、実現したセクションに戻って、順番に戻ると修正されます。例: パネルがアイテム 12 がセクション 1 にあることを認識し、パネルがセクションごとに 10 アイテムを見積もった場合 (セクション 0 が最初)、セクション 9 にジャンプすると、パネルは 100 番目のアイテムを最初に表示されるアイテムとして表示します(これは、セクション 1 から 9 まででセクションごとにちょうど 10 個のアイテムがある場合にのみ正しくなります)。しかし、セクション 1 に戻って、セクション 9 に到達するまですべてのセクションに順番にアクセスすると、

3- 通常、スクロールビューアー内の WrapPanel は垂直方向と水平方向にスクロールできますが、仮想化できるのは 1 方向のみであるため、このラップパネルはパネルの向きに直交する方向にのみスクロールします (つまり、仮想化パネルの高さ/明示的に幅)。

コピー元; http://virtualwrappanel.codeplex.com/

固定セルの意味がわかりませんでしたが、アイテムごとに幅と高さを固定しておけば、私が提供した仮想化 (VirtualWrapPanel) よりも優れた仮想化を記述できます。コードを参照して、何が起こっているのかを理解してください。

あなたが「まったく機能しない」と呼ぶのは、おそらく、WrapPanel とまったく同じように機能する素敵な VirtualizingWrapPanel を作成することができないためです (アイテムの特定の行が次のアイテムなどに依存するという事実のため)。各アイテムの幅/高さが同じであるという事実と組み合わせると、もっとうまくいくと思います。

また、これらの記事に基づいて独自のソリューションを作成することから始めることもできます。

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

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

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

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

于 2012-10-11T13:41:53.203 に答える
0

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

   }
于 2017-03-06T07:03:28.997 に答える