2012-03-13 25 views
0

子要素をStackPanelまたはGrid(可変の行数で、StackPanelと見なされる)のいずれかでレイアウトするカスタムコンポーネントを作成したいとします。項目は、いくつかの設定を保持するカスタム要素/オブジェクトです(いくつかのラベルとテキストボックスを表示するためにいくつかのコントロールが作成されます)。ItemsControlカスタムサブ要素のみを持つ

理想的には、成分(SpecializedCustomPanelItemCustomPanelItemのサブタイプである。)このように何らかの形で使用する必要があります。

<CustomPanel> 
    <CustomPanelItem Param1="value A" Param2="value B">Text</CustomPanelItem> 
    <CustomPanelItem Param1="value C">Other text</CustomPanelItem> 
    <SpecializedCustomPanelItem>More text</SpecializedCustomPanelItem> 
    <!-- The number of items is variable --> 
</CustomPanel> 

私は今しばらくItemsControlに読んだ、そしてそれはかなりよく私のニーズに合いました。アイテムのタイプを作成し、ItemsControlの中から利用可能なデータテンプレートを作成します。その後、彼らはすでにうまくいくはずです。

しかし、ItemsControlの中のアイテムに特定のタイプ(つまり、CustomPanelItemまたはサブタイプ)を指定したいと考えています。私は実際にItemsControlがこれを許可すると思っていましたが、ComboBoxまたはMenuItemのように、実際には任意のサブタイプを許可し、必要に応じてアイテムコンテナにラップします。

ItemsControlが実際に私が探しているものだと思っています。そのようなコントロールのほとんどが実装している選択やスクロールのような「派手な」ものは欲しくないからです。実際には、アプリケーション内の共通パターンへのシンプルなインターフェイスを構築して、それらのコンポーネントを自動生成し、Grid/StackPanelにレイアウトしたいだけです。

まだItemsControlを使用しているか、カスタムコンポーネントをさらに作成する必要がありますか?

+0

あなたのviewmodelからあなたの項目をバインドするつもりですか、彼らは単に静的にXAMLで宣言されていますか? – NVM

+0

これらは静的に宣言されていますが、内容(生成されたテキストボックス内の値)はおそらくバインディングを取得します。 – poke

+0

この場合、パネルにどのタイプを追加したのかをコンパイル時に知っています。実行時にコンパイル時に問題が発生する可能性はありません。したがって、このようなチェックはランタイムチェックではなく単体テストに適していますか? – NVM

答えて

1

これは、あなたはそれがあなたの項目を保持し、各項目を描画する方法を定義するItemContainerTemplateを設定しますパネルの種類を定義するためにItemsPanelTemplateだ設定することができますItemsControl

のために完璧に聞こえます。

項目は、彼らが何であるかのタイプに基づいて異なって描画されるべき場合、私はあなたがおそらく代わりに、動的に作成されたグリッドを使用したいと述べた暗黙のDataTemplatesを使用して代わりにItemContainerTemplate

<Window.Resources> 
    <DataTemplate DataType="{x:Type my:BasePanelItem}"> 
     <my:CustomPanelItem Param1="{Binding Param1}" Param2="{Binding Param2}" Content="{Binding SomeValue}" /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type my:SpecializedPanelItem}"> 
     <my:SpecializedCustomPanelItem Content="{Binding SomeValue}" /> 
    </DataTemplate> 
</Window.Resources> 


<ItemsControl ItemsSource="{Binding MyItems}"> 
    <!-- ItemsPanelTemplate --> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <my:CustomPanel /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

を設定することをお勧めしたいですStackPanelも同様です。もしあなたがそうしたら、私は自分のブログに投稿したGridHelpersに興味があるかもしれません。これは、あなたが本当にカスタムコンポーネントを必要としない。この場合ItemsPanelTemplate

<ItemsControl ItemsSource="{Binding MyCollection}"> 
    <!-- ItemsPanelTemplate --> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid local:GridHelpers.RowCount="{Binding RowCount}" 
        local:GridHelpers.ColumnCount="{Binding ColumnCount}" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 

    <!-- ItemContainerStyle --> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
      <Setter Property="Grid.Column" Value="{Binding ColumnIndex}" /> 
      <Setter Property="Grid.Row" Value="{Binding RowIndex}" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
</ItemsControl> 
3

Grid上の列/行の数をバインドすることが可能になります。 ItemsPanelタイプを必要なタイプに変更する+アイテムの複数のテンプレートを使用してトリックを行う必要があります。

しかし見出しに質問に答える:あなただけのアイテムの特定のタイプを受け入れるようにコントロールするアイテムを強制したい場合は、

作成する必要があります。 CustomItemsControl
b。メモリは、これは他の種類があることを許可しないようにするItemsControlを強制する必要がありますあります場合は、属性

[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(CustomItemsControlItem))] 

を宣言する必要がありCustomItemsControlためCustomItemsControlItemその後

はその後も

protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new CustomItemsControlItem(); 
     // You can throw an exception here 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is CustomItemsControlItem; 
    } 

にする必要があります子として追加され、例外をスローする必要があります。次に、XAMLで項目を追加するときに設定できるDependencyPropertiesを定義して、CustomItemsControlItem内でいくつかの魔法を実行できます。

しかし、正しく表示したいViewModelに複数の型がある場合でも、ViewModel型を対象とするCustomItemsControlItemには複数のテンプレートを用意するのが正しい方法です。

これが役に立ちます。

+0

+1、アイテムが 'Window'または' Popup'のみである「Open Windows Preview Carousel」コントロールのために使用したものです。 –

関連する問題