Reference Sorceを読む。 ItemContainerGenerator - 1Page 

昨日のPanelの記事でちらほら出てきたItemContainerGeneratorについて今日は読んでいきます。

この記事の共通項目

共通的に出てくる列挙型を先に記載しておきます。
GeneratorPosition 構造体 (System.Windows.Controls.Primitives)
GeneratorDirection 列挙型 (System.Windows.Controls.Primitives)

ItemContainerGenerator

Reference Source

概要

    /// <summary>
    /// An ItemContainerGenerator is responsible for generating the UI on behalf of
    /// its host (e.g. ItemsControl).  It maintains the association between the items in
    /// the control's data view and the corresponding
    /// UIElements.  The control's item-host can ask the ItemContainerGenerator for
    /// a Generator, which does the actual generation of UI.
    /// </summary>
    public sealed class ItemContainerGenerator : IRecyclingItemContainerGenerator, IWeakEventListener
    {

Panelの場合、実際のUI要素はこのジェネレータが生成しています。
規模が大きいので、大体の役割を理解するためにまずはインターフェース(IRecyclingItemContainerGenerator, IWeakEventListener)を確認しましょう。

IRecyclingItemContainerGenerator

Reference Source
概要

    /// <summary>
    ///     Interface through which a layout element (such as a panel) marked
    ///     as an ItemsHost communicates with the ItemContainerGenerator of its
    ///     items owner.
    ///     
    ///     This interface adds the notion of recycling a container to the 
    ///     IItemContainerGenerator interface.  This is used for virtualizing
    ///     panels.
    /// </summary>
    public interface IRecyclingItemContainerGenerator : IItemContainerGenerator

仮想化としてリサイクルを行うコンテナのインターフェースです。
継承元のIItemContainerGeneratorについては後ほど見ていきましょう。

インターフェース

  • void Recycle(GeneratorPosition position, int count);
    リサイクルする範囲を指定します。

IItemContainerGenerator

Reference Source

概要

    /// <summary>
    ///     Interface through which a layout element (such as a panel) marked
    ///     as an ItemsHost communicates with the ItemContainerGenerator of its
    ///     items owner.
    /// </summary>
    public interface IItemContainerGenerator

インターフェース

  • IRecyclingItemContainerGenerator ItemContainerGenerator GetItemContainerGeneratorForPanel(Panel panel);
    パネルを指定してジェネレータを返します。

  • IDisposable StartAt(GeneratorPosition position, GeneratorDirection direction);

  • IDisposable StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem);
    指定された位置と方向からジェネレータの作成を開始します。 注意としてはGenerateNextを呼びだすまえにStartAtを呼び出す必要があり。 IDisposableを返却しているため呼び出し元でDisposeの管理を可能としています。

  • DependencyObject GenerateNext();
    次の項目を表示するための要素を返却します。初期位置や方向性はStartAtで指定された内容がベースとなります。
    そのため事前にStartAtメソッドをコールする必要あり。

  • DependencyObject GenerateNext(out bool isNewlyRealized);
    GenerateNext()のオーバーロード。違いとしてIsNewlyRealizedは次の要素があればTrue.なければFalseが設定されます。

  • void PrepareItemContainer(DependencyObject container);
    指定された要素がUIとして機能するように準備するメソッドです。 (スタイルや親要素からの情報伝達など)
    このメソッド単独での説明は分かりにくいので、大まかなライフサイクルとともに後ほど記載します。

  • void RemoveAll();
    全てのジェネレータ要素を削除します。

  • void Remove(GeneratorPosition position, int count);
    指定されたポジションから指定された要素分を削除します。

  • GeneratorPosition GeneratorPositionFromIndex(int itemIndex);
    itemのIndexを元にGeneratorPositionを返却します。

  • int IndexFromGeneratorPosition(GeneratorPosition position);
    GeneratorPositionからindexを返却します。

IWeakEventListener

Reference Source

概要

    /// <summary>
    /// A class should implement this interface if it needs to listen to
    /// events via the centralized event dispatcher of WeakEventManager.
    /// The event dispatcher forwards an event by calling the ReceiveWeakEvent
    /// method.
    /// </summary>
    /// <remarks>
    /// The principal reason for doing this is that the event source has a
    /// lifetime independent of the receiver.  Using the central event
    /// dispatching allows the receiver to be GC'd even if the source lives on.
    /// Whereas the normal event hookup causes the source to hold a reference
    /// to the receiver, thus keeping the receiver alive too long.
    /// </remarks>
    public interface IWeakEventListener
    {
        /// <summary>
        /// Handle events from the centralized event table.
        /// </summary>
        /// <returns>
        /// True if the listener handled the event.  It is an error to register
        /// a listener for an event that it does not handle.
        /// </returns>
        bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e);
    }

イベントを弱参照で管理するリスナーのインターフェースです。
超ざっくりいうと通常イベント(+=で登録するやつ)だと依存関係が強くなりガベージコレクションが出来ず、
メモリが解放されない可能性があるので弱参照でイベントを管理するリスナーを提供する機能のインターフェースです。

インターフェース

  • bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e);
    リスナーがイベントを処理した場合にtrueを返却します。