2013-02-01 17 views
13

Birden çok türde görünüm modellerini içeren bir ObservableCollection var ve her GridViewColumn CellTemplates ürününün her birinde bir DataTemplate oluşturmak istiyorum. Bu basit örnekte bir ViewModel tabanı oluşturabilirdim, ancak bunu sadece xaml'den yapabilmeyi isterdim. Aşağıdaki xaml, her bir CellTemplate için DataTemplates'lerden birinin kullanılacağı şeyi yapmaya çalıştığımı gösterir.GridViewColumn CellTemplate içindeki her bir DataType için DataTemplate

GridViewColumn.Resources varsa, orada DataTemplates tanımlamak sonra CellTemplate içinde ContentPresenter ile bir DataTemplate kullanın, ancak açıkçası bunu yapamıyorum. Bir TemplateSelector'a ihtiyacım olabileceğini düşünüyorum ama nereden başlayacağımı bilmiyorum.

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

cevap

30

Buradan gidebileceğiniz birkaç farklı yol vardır. Bir DataTemplateSelector yazıp GridViewColumn.CellTemplateSelector özelliğine o atayabilirsiniz:

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

Sonra yere Kaynaklarına tüm şablonları taşıyabilirsiniz - burada sadece kısalık için ListView içinde sıkışmış ettik:

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

Alternatif olarak, hepsini XAML'de tutmak istiyorsanız, sizin için doğru şablonları çözmek için DataTypes'e güvenebilirsiniz. Normalde onları en yakın kapsayıcıların Kaynaklar koleksiyonuna koyarsınız ancak maalesef GridViewColumn bir UI öğesi değildir, bu yüzden bir Kaynaklar koleksiyonunuz yoktur. Sen kendi yazdığınız şablonları tutabilir her hücre için bir ContentControl içinde ekleyerek bu sorunun üstesinden gelebilirsiniz:

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

Her iki şekilde de aynı sonucu vermelidir.

+0

Mükemmel. Göz önünde bulundurduğum her iki yaklaşım için de detaylı cevaplar sağladığınız için teşekkür ederiz. – scuba88

+0

Geez, saatlerce savrulma sonrası sooo yakındım ama sen çivilenmişsin. Benim hatam, doğru bir şekilde işaret ettiğim gibi, 'İçerik' in aksine 'ContentControl'ün' DataContext'ini bağladığım oldu. Kudos ve teşekkürler. –

+0

İnsanların cevabında gerçekten zaman geçirdiklerinde bunu seviyorum. Sağladığınız ayrıntıda belirgindir. İyi iş. +1. – cplotts

İlgili konular