6

私はここに提示されたチュートリアルに従っています:

http://blogs.msdn.com/b/dancre/archive/tags/virtualizingtilepanel/

それらの実装では、子のサイズを追跡する virtualizingtilepanel に依存関係プロパティがあります。ただし、WPF ライブラリの virtualizingstackpanel では、子要素のサイズをプロパティとして設定する必要はありません。ただし、アイテムをインスタンス化せずに、仮想化スタックパネルがパネル内のどのアイテムが表示されるかを計算する方法がわかりません。

アイテム コンテナーのサイズを知るにはメジャー パスが必要だと思いますが、最初にアイテムをインスタンス化せずにどうすればそれを知ることができるでしょうか?

私の目標は、treeviewitem を含むパネルを作成してそれらを仮想化することですが、virtualizingtilepanel の例に従うと、トップレベルのアイテムしか仮想化できません。

どのアイテムが表示されているかを計算する方法を変更する必要がありますが、サイズを知らずに実際にアイテムをインスタンス化することなく、どのアイテムが表示されているかを知る方法がわかりません。

編集: ちょっと待って、ツリービューアイテムの中に入るオブジェクトをすぐにインスタンス化し、それらを使用してサイズを計算するのでしょうか?

4

2 に答える 2

3

VirtualizingStackPanel には 2 つのモードがあります。1 つは ScrollToContent と呼ばれ、そのようなモードでは、VirtualizingStackPanel はアイテムのインデックスを使用します。例として、10 個のアイテムが表示され、1000 個のアイテムがあるため、ScrollBar は小さく表示されます。

2 番目のモードは ScrollToPixels と呼ばれ、このモードでは VirtualizingStackPanel が仮想化されたアイテムと実現されたアイテムのリストを管理します。項目がまだ認識されていない場合、VirtualizingStackPanel はその MinHeight 値を使用します。これは、Microsoft の場合、ユーザーによって設定されていない場合は 16 ピクセルです。例として、10 個のアイテムが表示され、各アイテムの高さは 20 ピクセルです。ビューポートの高さは 200 ピクセルになりますが、アイテムの総数が 1000 であるため、範囲は 200 + (1000 - 10 ) * 16 = 16040 ピクセルになります。ScrollBar も小さく、適切な比率で表示されます。

結局のところ、VirtualizingStackPanel は複雑なものであり、ほとんどの場合うまく機能します。また、垂直方向と水平方向の仮想化も可能です。これは素晴らしいことです。独自の VirtualizingStackPanel を作成する場合は、車輪の再発明をやめることをお勧めします。マイクロソフトの連中が行ったのと同じことをコードで行うことになるので、他の誰かが既に VirtualizingStackPanel を開発したときに時間を浪費するのはなぜですか :)

RedGate ツールで VirtualizingStackPanel を反映させました。これを見てください:

    private Size ContainerSizeForItem(ItemsControl itemsControl, object item, int index, out UIElement container)
    {
        Size containerSize;
        container = index >= 0 ? ((ItemContainerGenerator)Generator).ContainerFromIndex(index) as UIElement : null;

        if (container != null)
        {
            containerSize = container.DesiredSize;
        }
        else
        {
            // It's virtualized; grab the height off the item if available.
            object value = itemsControl.ReadItemValue(item, _desiredSizeStorageIndex);
            if (value != null)
            {
                containerSize = (Size)value;
            }
            else
            {
                //
                // No stored container height; simply guess.
                //
                containerSize = new Size();


                if (Orientation == Orientation.Horizontal)
                {
                    containerSize.Width = ContainerStackingSizeEstimate(itemsControl, /*isHorizontal = */ true);
                    containerSize.Height = DesiredSize.Height;
                }
                else
                {
                    containerSize.Height = ContainerStackingSizeEstimate(itemsControl, /*isHorizontal = */ false);
                    containerSize.Width = DesiredSize.Width;
                }
            }
        }

        return containerSize;
    }

    private double ContainerStackingSizeEstimate(IProvideStackingSize estimate, bool isHorizontal)
    {
        double stackingSize = 0d;

        if (estimate != null)
        {
            stackingSize = estimate.EstimatedContainerSize(isHorizontal);
        }

        if (stackingSize <= 0d || DoubleUtil.IsNaN(stackingSize))
        {
            stackingSize = ScrollViewer._scrollLineDelta;
        }

        return stackingSize;
    }

ScrollViewer を反映すると、次のようになります。

internal const double _scrollLineDelta = 16.0;   // Default physical amount to scroll with one Up/Down

ご覧のとおり、コンテナが利用できない場合、サイズは推測されます。つまり、Microsoft のデフォルトである 16.0 ピクセルに設定されます。

ところで、.Net 3.5以降、たとえばTreeViewを参照してください。:) :)

于 2013-10-16T06:45:07.703 に答える
3

VirtualizingStackPanel アイテムはコンテンツ サイズに直接基づいていません。インデックスに基づいて子を処理します。
スタック方向の範囲は、純粋に子の数によって決まります。VirtualizingStackPanel は、その子を認識するまで、その子のサイズを認識しません。

ビューポートがスクロールすると次のアイテムが実現されるため、仮想化でスムーズなスクロールを使用できないのはこのためです (ピクセル スクロールが追加された .Net4.5 を除く)。

VirtualizingPanelWPF での作成に関する素晴らしい 4 部構成のブログがありますVirtualizingWrapPanelVirtualization

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

于 2013-10-16T00:15:10.503 に答える