Reference Sorceを読む。 ItemBlock - 1Page 


Reference Source


        //  Private Nested Classes
        // The ItemContainerGenerator uses the following data structure to maintain
        // the correspondence between items and their containers.  It's a doubly-linked
        // list of ItemBlocks, with a sentinel node serving as the header.
        // Each node maintains two counts:  the number of items it holds, and
        // the number of containers.
        // There are two kinds of blocks - one holding only "realized" items (i.e.
        // items that have been generated into containers) and one holding only
        // unrealized items.  The container count of a realized block is the same
        // as its item count (one container per item);  the container count of an
        // unrealized block is zero.
        // Unrealized blocks can hold any number of items.  We only need to know
        // the count.  Realized blocks have a fixed-sized array (BlockSize) so
        // they hold up to that many items and their corresponding containers.  When
        // a realized block fills up, it inserts a new (empty) realized block into
        // the list and carries on.
        // This data structure was chosen with virtualization in mind.  The typical
        // state is a long block of unrealized items (the ones that have scrolled
        // off the top), followed by a moderate number (<50?) of realized items
        // (the ones in view), followed by another long block of unrealized items
        // (the ones that have not yet scrolled into view).  So the list will contain
        // an unrealized block, followed by 3 or 4 realized blocks, followed by
        // another unrealized block.  Fewer than 10 blocks altogether, so linear
        // searching won't cost that much.  Thus we don't need a more sophisticated
        // data structure.  (If profiling reveals that we do, we can always replace
        // this one.  It's totally private to the ItemContainerGenerator and its
        // Generators.)
        // represents a block of items
        private class ItemBlock

        // represents a block of unrealized (ungenerated) items
        private class UnrealizedItemBlock : ItemBlock

        // represents a block of realized (generated) items
        private class RealizedItemBlock : ItemBlock

3つともprivateなのはItemContainerGeneratorのネストクラスだからですね。 概要コメントが長いですが、要約すると
アイテムとコンテナ間の関係性を管理する機能を提供します。またブロックは2種類(生成済ブロック / 未生成なブロック)存在しており、 目的としては仮想化を実現するために2種類のブロックが存在しています。 ちなみに生成済ブロックがRealizedItemBlock、未生成ブロックがUnrealizedItemBlockですね。

ItemBlockが提供している役割としてはItemBlock同士の繋がりを表現しています。 ソースを交えながら見ていきます。

       private class ItemBlock
            public const int BlockSize = 16;
            public int ItemCount { get { return _count; } set { _count = value; } }
            public ItemBlock Prev { get { return _prev; } set { _prev = value; } }
            public ItemBlock Next { get { return _next; } set { _next = value; } }
            public virtual int ContainerCount { get { return Int32.MaxValue; } }
            public virtual DependencyObject ContainerAt(int index) { return null; }
            public virtual object ItemAt(int index) { return null; }

コレクション等ではなく自身で次の要素(ItemBlock)、前の要素(ItemBlock)の要素を持ち管理しています。 この管理のメリットとしては、イテレーションのように再帰処理などで柔軟に要素に対する処理が可能になることですね。

a - b - c - d
のうちcをRemoveをすると勿論、下記のようになります。 a - b - d


            public void Remove()
                Prev.Next = Next;
                Next.Prev = Prev;



a(RealizedItemBlock) - b(RealizedItemBlock) - c(RealizedItemBlock) - d(UnrealizedItemBlock) となり、cまで生成済(スクロールバーなどの表示領域)、dは非表示領域にいるため生成されていないという状態がみえたりします。 この辺りはItemContainerGeneretarにて流れを書ければと思います。