コンテンツへスキップ
XamDockManager 要素の ItemsSource

XamDockManager 要素の ItemsSource

TabGroupPaneのItemsSourceをコレクションにバインドすることについて、多くの人から質問が寄せられています。これはTabGroupPaneでサポートされていないため、理由を説明し、別のアプローチを提供すると思いました。

4分で読めます

TabGroupPaneのItemsSourceをコレクションにバインドすることについて、多くの人から質問が寄せられています。これはTabGroupPaneでサポートされていないため、理由を説明し、別のアプローチを提供すると思いました。

DocumentContentHostまたは特定のSplitPaneをコレクションにバインドしようとしている場合でも、このソリューションではそれも可能になるため、読み進める必要があります。

TabGroupPane は派生した ItemsControl であり、TabGroupPane に表示される ItemsSource プロパティは基本 ItemsControl クラスのものです。ItemsControl は、実際には、ItemsSource 内の項目に対して作成されたすべてのコンテナーが、その ItemsControl 内でホストされる (具体的には、ItemsPanel プロパティで示される Panel によってホストされる) ように設計されています。そのため、アイテムがコレクションに追加されると、アイテムは自動的に ItemsPanel の Children にプッシュされるか、VirtualizingPanel の場合は、パネルがハイドレートされるタイミングやコンテナーを制御するかのどちらかです。また、ItemsSource を設定すると、その Items コレクションを直接変更することはできず、変更すると ItemCollection によって例外がスローされます。

TabGroupPaneについて考えると、含まれるアイテム、つまりItemsコレクションを操作できる必要があります。これにはいくつかの理由が考えられます。たとえば、エンド ユーザーがペインをピン留め/ピン留め解除したり、ペインをグループ内またはグループ外にドラッグしたり、子の 1 つのドッキング/フローティング状態を変更したりした場合などです。コントロールの項目が ItemsSource によって提供されている場合 (Items コレクションは変更できないため)、コントロールは ItemsSource を介した Items コレクションのバインドをサポートできません。

では、ItemsSourceプロパティを使用せずにこれをサポートするにはどうすればよいでしょうか。考えてみれば、必要なのはItemContainerGeneratorに類似したものです。これは、ItemsControl とそれに関連付けられた ItemsPanel によって、目的の型ではない項目のコンテナー/要素を生成するために使用されるクラスです。したがって、ListBox の場合、その種類ではない項目に対して ListBoxItem インスタンスが生成されます。残念ながら、ItemContainerGeneratorは公開できません。

そこで、私が採用することにしたアプローチは、ContainerFactoryBase という名前の独自の ItemContainerGenerator 型クラスを作成し、ソース コレクションを指定でき、コンテナの関連コレクションを維持できるようにすることでした。コレクションの内容に基づいて、コレクションが変更通知を発生させると、派生クラスが適切なコンテナー (IsItemItsOwnContainer や GetContainerForItem など) を作成し、そのコンテナーをアイテムに関連付けるために使用できる ItemsControl と同様のメソッドがそれ自体で呼び出されます (例: ApplyItemContainerStyle や PrepareContainerForItem)。ソース コレクション内の項目が追加/削除/移動されたときにメソッドを呼び出し、派生クラスが関連付けられたコンテナーに対して適切なアクションを実行できるようにします。

次に、各項目のコンテナとして ContentPane インスタンスを作成し、関連付けられたターゲットに追加する ContentPaneFactory という名前の派生クラスを作成しました。このクラスは、ContentPane のプロパティをデータ項目のプロパティ (Header、Content、TabHeader プロパティなど) にバインドするために使用できるいくつかのパス プロパティを公開します。その他のプロパティについては、ContainerStyle プロパティを使用して ContentPane の Style を指定するか、ItemBindings コレクションを使用できます。最後に、ContentPane が作成されたときに添付イベント (InitializeContentPane) も発生させ、必要なプログラムによる初期化を実行できるようにします。

これを使いやすくするために、ファクトリを特定のターゲットに関連付けるために使用される添付プロパティを作成しました。したがって、ContentPaneFactory.PaneFactory プロパティを、TabGroupPane、SplitPane、または DocumentContentHost のいずれかの ContentPaneFactory インスタンスに設定し、それが新しい ContentPane インスタンスが追加されるターゲット要素です。

    <igDock:DocumentContentHost >
        <igExtensions:ContentPaneFactory.PaneFactory>
            <!-- Binds to the Documents property of the DataContext. -->
            <igExtensions:ContentPaneFactory 
               ItemsSource="{Binding Documents}"
               HeaderPath="Name"
               ContentPath="." />
        </igExtensions:ContentPaneFactory.PaneFactory>
    </igDock:DocumentContentHost>

サンプルはこちらから入手できます。

デモを予約