web-dev-qa-db-ja.com

Panel.IsItemsHostは正確に何をしますか?

Panel.IstItemsHostに使用される添付プロパティ?

ItemsControlのItemsContainerテンプレートに設定する人の例はたくさんありますが、MSDNでのドキュメント化されていないため、プロパティを設定することで得られる理由や利点については説明されていません。

35
Armentage

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番目の方法でそれをしたことはありませんが、それが役立つかもしれない場所がいくつかあるかもしれないと思います。

37
user1228

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プロパティを設定しているという事実によって行われます。

12
Richard

詳細説明をお願いします!

上記の回答はすべて技術的には正しいものですが、IsItemsPanelControlTemplateとどのように相関し、ItemsPresenterとそれに対応するItemsPanelプロパティが存在する(または存在しない)かを示していないように感じます。この回答は、それらのことを明らかにし、うまくいけば、それぞれをいつ使用すべきか、または使用すべきでないかを明確にしようとします。

ItemsControls、Panels、IsItemsHost、オーマイ!

ItemsControlは、単にアイテムのコレクションを表示するコントロールです。これは、最初にこれらのアイテムごとにItemContainerを生成し、次にそれらのコンテナーを特定の「ホスト」パネルに挿入(または削除)し、最後にそのパネルがコンテナーを表示用にレイアウトします。

コンテナをホストするために使用される特定のパネルは、ItemControlプロパティが「True」に設定されているIsItemsHostの階層で最初に見つかったパネルです。どのパネルであるかを指定する方法は2つあります。

  1. ItemsPresenterControlTemplateに挿入し、次にItemsPanelプロパティを設定するか、または...
  2. PanelControlTemplateに直接挿入し、そのIsItemsHostを「True」に明示的に設定する。

しかし、どちらを使用し、その理由は何ですか?読んで調べてください!

ItemsPresenter-「HaveItYourWay!」

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を使用する利点は、コントロールのコンシューマーがパネルを簡単に置き換えることができることです完全に再テンプレート化する必要はありません)あなたのコントロール全体。

IsItemsHost-「マイウェイまたはハイウェイ!」

ただし、コントロールがカスタムパネルの実装に依存していて、他の何かが機能を壊してしまうために、誰かがパネルを変更できないようにするにはどうすればよいでしょうか。その場合、しないテンプレートで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プロパティも設定して、デフォルトのパネルを指定してください。

ただし、コントロールが使用するパネルを「ロック」したい場合は、ItemsPresenterControlTemplateを使用しないでくださいnot。代わりに、テンプレートで直接使用する特定のパネルを指定してから、そのIsItemsHostプロパティを「True」に設定します。

注:技術的には3番目のシナリオがありますが、これは間違いなくより一般的です。あなたは他のユーザーが使用するものを作成するコントロール作成者ではなく、ItemsControl(たとえばListBox)を特別な用途のために再テンプレート化するだけです。あなた自身のアプリケーション。

その場合、あなたはコントロールの最終的な消費者であるため、下流の他の消費者がパネルを変更する必要があることを心配する必要はほとんどないので、テンプレートで直接パネルを指定するだけでまったく問題ありません(ここでも、 IsItemsHost trueを設定し、ItemsPresenterとそれに関連するItemsPanelプロパティを後者として使用することを心配しないでください。後者は有効ですが、実際の利点なしに不必要な複雑さを追加するだけです。

これが何が起こっているのかを正確に明らかにすることを願っています。

10
Mark A. Donohoe