2013-02-01 16 views
13

Ho una ObservableCollection che contiene i modelli di visualizzazione di più tipi e vorrei creare un DataTemplate per ogni tipo all'interno di ogni CellTemplates del mio GridViewColumn. In questo semplice esempio potrei creare un ViewModel di base, ma mi piacerebbe poterlo fare solo da xaml. L'xaml qui sotto mostra cosa sto cercando di fare, dove uno dei DataTemplates dovrebbe essere usato per ogni CellTemplate.DataTemplate per ogni DataType in GridViewColumn CellTemplate

Se esistesse una GridViewColumn.Resources, definirò i DataTemplate quindi utilizzerò un DataTemplate con ContentPresenter nel CellTemplate, ma ovviamente non posso farlo. Sto pensando che potrebbe essere necessario un TemplateSelector, ma non sono sicuro da dove cominciare.

<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> 

risposta

30

Ci sono diversi modi per andare qui. Si potrebbe scrivere un DataTemplateSelector e assegnare che alla proprietà 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; 
    } 
} 

Quindi è possibile spostare tutti i modelli di risorse da qualche parte - qui ho appena attaccato nella ListView per brevità:

<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> 

In alternativa, se vuoi mantenere tutto in XAML puoi contare su DataTypes per risolvere i modelli giusti per te. Normalmente li inseriresti nella raccolta Risorse del contenitore più vicino ma sfortunatamente GridViewColumn non è un elemento dell'interfaccia utente, quindi non ha una raccolta di risorse. È possibile aggirare il problema aggiungendo in un ContentControl per ogni cella che può contenere i propri modelli tipizzati:

<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> 

In entrambi i casi dovrebbe dare lo stesso risultato.

+0

Perfetto. Grazie per aver fornito risposte dettagliate per entrambi gli approcci che avevo considerato. – scuba88

+0

Geez, ero così vicino dopo aver agitato per ore, ma l'hai inchiodato. Il mio errore era che stavo legando il 'DataContext' del' ContentControl', in contrasto con il 'Content' come si indica correttamente. Complimenti e grazie. –

+0

Mi piace quando le persone passano del tempo nella loro risposta. È evidente nei dettagli che hai fornito. Bel lavoro. +1. – cplotts

Problemi correlati