Panel.IstItemsHost
に使用される添付プロパティ?
ItemsControlのItemsContainerテンプレートに設定する人の例はたくさんありますが、MSDNでのドキュメント化されていないため、プロパティを設定することで得られる理由や利点については説明されていません。
ItemsControlがあるとします。スクロールするとアイテムが出入りするカスタムパネルを使用したいと思います。それはSwoopPanelと呼ばれます。では、SwoopPanelを使用して作成したテンプレートを含めるようにItemsControlに指示するにはどうすればよいですか?
手っ取り早い方法は、ItemsControlでItemsPanelを設定することです。
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<lol:SwoopPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
ただし、それがうまくいかない場合もあります。 UIでのSwoopPanelの表示方法をカスタマイズしたい場合があります。これを回避する唯一の方法は、ItemsControlのコントロールテンプレートを変更することです。これで、SwoopPanelをコントロールテンプレートに直接追加し、プロパティを使用して、ItemsControlが作成するすべてのテンプレートアイテムを配置するItemsHostとしてマークすることができます。
<Style TargetType="ItemsControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Border CornerRadius="5">
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<lol:SwoopPanel IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
あなたはそれを何らかの方法で行う必要がありますか?いいえ。一方が他方よりも有利ですか? 2番目の方法では、UIをより細かく制御でき、最初の方法の方が簡単です。本当に、あなたの選択をしてください。私は個人的に2番目の方法でそれをしたことはありませんが、それが役立つかもしれない場所がいくつかあるかもしれないと思います。
http://msdn.Microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v = vs.90).aspx を参照してください。
基本的に、この投稿の内容は、リストボックスのControlTemplateを置き換えて新しいレイアウトが必要な場合は、一部のパネルでIsItemsHost = trueを設定することです。 StackPanel。次に、リストボックス内のすべてのアイテムがStackPanelの子として自動的に追加されます。リストボックスの向きが水平の場合、リストボックスは水平になります。
もう1つの方法は、ListBoxのItemsPanelプロパティをItemsTemplateに設定し、そのテンプレートにStackPanelを設定することです。この場合、ListBoxアイテムは、最初の場合と同じようにStackPanelの子に追加されます。ただし、IsItemsHost = trueを設定する必要はありません。まったく効果がありません。これは、ItemsPanelプロパティを設定しているという事実によって行われます。
上記の回答はすべて技術的には正しいものですが、IsItemsPanel
がControlTemplate
とどのように相関し、ItemsPresenter
とそれに対応するItemsPanel
プロパティが存在する(または存在しない)かを示していないように感じます。この回答は、それらのことを明らかにし、うまくいけば、それぞれをいつ使用すべきか、または使用すべきでないかを明確にしようとします。
ItemsControl
は、単にアイテムのコレクションを表示するコントロールです。これは、最初にこれらのアイテムごとにItemContainer
を生成し、次にそれらのコンテナーを特定の「ホスト」パネルに挿入(または削除)し、最後にそのパネルがコンテナーを表示用にレイアウトします。
コンテナをホストするために使用される特定のパネルは、ItemControl
プロパティが「True」に設定されているIsItemsHost
の階層で最初に見つかったパネルです。どのパネルであるかを指定する方法は2つあります。
ItemsPresenter
をControlTemplate
に挿入し、次にItemsPanel
プロパティを設定するか、または...Panel
をControlTemplate
に直接挿入し、そのIsItemsHost
を「True」に明示的に設定する。しかし、どちらを使用し、その理由は何ですか?読んで調べてください!
ControlTemplate
などのItemsControl
の一般的なListBox
では、テンプレートはその中のどこかにItemsPresenter
を指定します。これは、その使用方法を示す簡略化された抜粋です。
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
ご覧のとおり、テンプレートの中央にあるItemsPresenter
内にScrollViewer
が指定されています。ただし、表示されていないのは、アイテムをレイアウトするための実際のパネルです。
では、テンプレートにパネルが定義されていない場合、それはどこから来たのでしょうか?そこで、ItemsPanel
プロパティが登場します。その名前が示すように、このプロパティは、アイテムをホストおよびレイアウトするために使用されるパネルを定義します。ただし、そのパネルがControlTemplate
のどこに表示されるかはわかりません。
これでItemsPresenter
に戻ります。つまり、基本的に「ItemsPanel
プロパティが設定されたら、そのパネルをここに挿入し、そのIsItemsHost
を「True」に自動的に設定する」というプレースホルダーです。
ItemsPresenter
のテンプレートでItemsControl
を使用する利点は、コントロールのコンシューマーがパネルを簡単に置き換えることができることです完全に再テンプレート化する必要はありません)あなたのコントロール全体。
ただし、コントロールがカスタムパネルの実装に依存していて、他の何かが機能を壊してしまうために、誰かがパネルを変更できないようにするにはどうすればよいでしょうか。その場合、しないテンプレートでItemsPresenter
を使用します。代わりに、使用するパネルを正確に指定する必要があります。
ここでIsItemsHost
プロパティが役立ちます。 ControlTemplate
のパネルに設定すると、ItemsControl
が何に設定されているかに関係なく、その特定のパネルを使用して生成されたコンテナーをホストするようにItemsPanel
に指示します。 ItemsPanel
プロパティは基本的に無視されます。
上記と同じ例ですが、ItemsPresenter
ではなく、SpecializedPanel
をハードコーディングしてアイテムをレイアウトします。 IsItemsHost
プロパティを「True」に設定することにより、アイテムをホストするために使用するパネルであることを示します。
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<SpecializedPanel IsItemsHost="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
この場合、テンプレートはItemsPresenter
を使用せず、代わりにIsItemsHost
が「True」に設定されたパネルを直接含むため、ControlTemplate
全体を完全に置き換える以外に、ユーザーがそのパネルを変更する方法はありません。
要約すると、あなたがコントロールの作成者であり、コントロールのコンシューマーにアイテムのレイアウトに使用されるパネルを交換する機能を提供したい場合は、ItemsControl
を使用してItemsPresenter
のテンプレートを定義します。テンプレートでItemsPanel
プロパティも設定して、デフォルトのパネルを指定してください。
ただし、コントロールが使用するパネルを「ロック」したい場合は、ItemsPresenter
でControlTemplate
を使用しないでくださいnot。代わりに、テンプレートで直接使用する特定のパネルを指定してから、そのIsItemsHost
プロパティを「True」に設定します。
注:技術的には3番目のシナリオがありますが、これは間違いなくより一般的です。あなたは他のユーザーが使用するものを作成するコントロール作成者ではなく、
ItemsControl
(たとえばListBox
)を特別な用途のために再テンプレート化するだけです。あなた自身のアプリケーション。その場合、あなたはコントロールの最終的な消費者であるため、下流の他の消費者がパネルを変更する必要があることを心配する必要はほとんどないので、テンプレートで直接パネルを指定するだけでまったく問題ありません(ここでも、
IsItemsHost
trueを設定し、ItemsPresenter
とそれに関連するItemsPanel
プロパティを後者として使用することを心配しないでください。後者は有効ですが、実際の利点なしに不必要な複雑さを追加するだけです。
これが何が起こっているのかを正確に明らかにすることを願っています。