17

複数のタイプのビュー モデルを含む ObservableCollection があり、各 GridViewColumn の CellTemplates 内の各タイプの DataTemplate を作成したいと考えています。この単純な例では、基本の ViewModel を作成できましたが、xaml からだけ作成できるようにしたいと考えています。以下の xaml は、私がやろうとしていることを示しています。ここでは、CellTemplate ごとに DataTemplates の 1 つが使用されます。

GridViewColumn.Resources があった場合、そこで DataTemplates を定義し、CellTemplate で ContentPresenter を含む DataTemplate を使用しますが、明らかにそれはできません。TemplateSelector が必要かもしれないと考えていますが、どこから始めればよいかわかりません。

<ListView ItemsSource={Binding GenericObservableCollection>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Type">
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
                        <TextBlock Text="Input"/>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
                        <TextBlock Text="Output"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Value">
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
                        <TextBlock Text="{Binding Property1}"/>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
                        <TextBlock Text="{Binding Property2}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>
4

1 に答える 1

36

ここに行く方法はいくつかあります。DataTemplateSelector を記述して、それをGridViewColumn.CellTemplateSelectorプロパティに割り当てることができます。

public class ViewModelTemplateSelector : DataTemplateSelector
{
    public DataTemplate InputTemplate { get; set; }
    public DataTemplate OutputTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        return (item is ActionInputViewModel) ? InputTemplate : OutputTemplate;
    }
}

次に、すべてのテンプレートをどこかのリソースに移動できます。ここでは、簡潔にするために ListView に貼り付けました。

    <ListView ItemsSource="{Binding GenericObservableCollection}">
        <ListView.Resources>
            <DataTemplate x:Key="InLabel" DataType="{x:Type vm:ActionInputViewModel}">
                <TextBlock Text="Input"/>
            </DataTemplate>
            <DataTemplate x:Key="OutLabel" DataType="{x:Type vm:ActionOutputViewModel}">
                <TextBlock Text="Output"/>
            </DataTemplate>
            <DataTemplate x:Key="InValue" DataType="{x:Type vm:ActionInputViewModel}">
                <TextBlock Text="{Binding Property1}"/>
            </DataTemplate>
            <DataTemplate x:Key="OutValue" DataType="{x:Type vm:ActionOutputViewModel}">
                <TextBlock Text="{Binding Property2}"/>
            </DataTemplate>
        </ListView.Resources>
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Type">
                    <GridViewColumn.CellTemplateSelector>
                        <vm:ViewModelTemplateSelector InputTemplate="{StaticResource InLabel}" OutputTemplate="{StaticResource OutLabel}"/>
                    </GridViewColumn.CellTemplateSelector>
                </GridViewColumn>
                <GridViewColumn Header="Value">
                    <GridViewColumn.CellTemplateSelector>
                        <vm:ViewModelTemplateSelector InputTemplate="{StaticResource InValue}" OutputTemplate="{StaticResource OutValue}"/>
                    </GridViewColumn.CellTemplateSelector>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

または、すべてを XAML に保持したい場合は、DataTypes を利用して適切なテンプレートを解決できます。通常は、最も近いコンテナーの Resources コレクションに配置するだけですが、残念ながら GridViewColumn は UI 要素ではないため、Resources コレクションはありません。独自の型付きテンプレートを保持できる各セルに ContentControl を追加することで、これを回避できます。

    <ListView ItemsSource="{Binding GenericObservableCollection}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Type">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding}">
                                <ContentControl.Resources>
                                    <DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
                                        <TextBlock Text="Input"/>
                                    </DataTemplate>
                                    <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
                                        <TextBlock Text="Output"/>
                                    </DataTemplate>
                                </ContentControl.Resources>
                            </ContentControl>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Value">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding}">
                                <ContentControl.Resources>
                                    <DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
                                        <TextBlock Text="{Binding Property1}"/>
                                    </DataTemplate>
                                    <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
                                        <TextBlock Text="{Binding Property2}"/>
                                    </DataTemplate>
                                </ContentControl.Resources>
                            </ContentControl>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

どちらの方法でも同じ結果が得られるはずです。

于 2013-02-01T19:38:30.320 に答える