web-dev-qa-db-ja.com

ビューモデルの複数のDataTemplatesを持つItemsControl

複数のDataTemplatesにテンプレートとしてキャンバスを使ってitemscontrolをバインドすることは可能ですか?

2つのコレクションがあり、タイプに応じて、キャンバスに別のコントロールを表示したいと考えています。

確かではありませんが、2つのObservableCollectionsを持つViewmodelについて考えることができます。たとえば、「Shapes」と「connections」があり、両方をキャンバスに表示したい場合はどうすればよいですか。ダイアグラムのシナリオの場合...

これをmvvmの方法で実行したいと思います。複数のDataTemplateアプローチが正しいかどうかはわかりませんが、これは私の頭に浮かびました。しかし、私はバインディングを頭の中でまっすぐにするのにまだ問題があります。 DataContextをViewModelに設定した場合、2つのコレクションを項目コントロールにバインドすることはできないようです... =(他のアイデアについてもオープンしています...

これは可能ですか?もしそうなら、バインディングはどのように見えますか

26
silverfighter

複数のObservableCollectionsを作成し、ItemsSourceCompositeCollection にバインドして、これらのコレクションを結合できます。

次に、XAMLでDataTemplatesプロパティを使用して、それぞれのタイプに異なるDataTypeを作成できます。これは、リソースに配置された場合にスタイルと同様に自動的に適用されます。 (CollectionContainersをバインドする必要がある場合、MSDNに表示されているXAMLでコンポジットを作成することもできます (もう少し難しい ですが))

コード例:

ObservableCollection<Employee> data1 = new ObservableCollection<Employee>(new Employee[]
{
    new Employee("Hans", "Programmer"),
    new Employee("Elister", "Programmer"),
    new Employee("Steve", "GUI Designer"),
    new Employee("Stefan", "GUI Designer"),
    new Employee("Joe", "Coffee Getter"),
    new Employee("Julien", "Programmer"),
});
ObservableCollection<Machine> data2 = new ObservableCollection<Machine>(new Machine[]
{
    new Machine("E12", "GreedCorp"),
    new Machine("E11", "GreedCorp"),
    new Machine("F1-MII", "CommerceComp"),
    new Machine("F2-E5", "CommerceComp")
});
CompositeCollection coll = new CompositeCollection();
coll.Add(new CollectionContainer() { Collection = data1 });
coll.Add(new CollectionContainer() { Collection = data2 });
Data = coll;
<ItemsControl ItemsSource="{Binding Data}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Employee}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}"/>
                <TextBlock Text=" ("/>
                <TextBlock Text="{Binding Occupation}"/>
                <TextBlock Text=")"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Machine}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Model}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Manufacturer}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

ここでは別のパネルを使用していますが、キャンバスでも同じでなければなりません。

50
H.B.

ObservableCollection<object>をViewModelに追加し、ItemsControlのSourceをこのコレクションにバインドします。

次に、さまざまなタイプのデータを異なる外観にするために、x:Keyを使用せずに、リソースでDataTypeを適切に設定して、2つのDataTemplatesを作成できます。その後、ItemsControlはアイテムに適切なDataTemplateを自動的に選択します。

6
Jens

データテンプレートセレクター here または here をご覧ください。

2
TerenceJackson