2013-02-01 4 views
13

여러 유형의 뷰 모델을 포함하는 ObservableCollection이 있고 각 GridViewColumn의 CellTemplates에서 각 유형에 대해 DataTemplate을 만들고 싶습니다. 이 간단한 예제에서는 기본 ViewModel을 만들 수 있지만 xaml에서이 작업을 수행 할 수 있기를 원합니다. 아래의 xaml은 DataTemplates 중 하나가 각 CellTemplate에 사용되는 위치를 보여줍니다.GridViewColumn의 각 DataType에 대한 DataTemplate CellTemplate

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> 

답변

30

여기에 갈 수있는 몇 가지 방법이 있습니다. 당신은 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> 

어느 쪽이든 동일한 결과가 나타납니다.

+0

Perfect. 내가 생각했던 두 접근법에 대한 상세한 해답을 주셔서 감사합니다. – scuba88

+0

이런, 몇 시간 동안 휘몰아 치고 난 후에 나는 너무 가까웠다. 그러나 네가 그것을 못 박았 다. 내 실수는 당신이 정확하게 지적한대로'Content'와는 반대로,'ContentControl'의'DataContext'를 묶는 것이 었습니다. 명성과 감사. –

+0

나는 사람들이 실제로 그들의 대답에 시간을 할애 할 때 그것을 좋아한다. 당신이 제공 한 세부 사항에서 분명합니다. 좋은 작업. +1. – cplotts

관련 문제