2015-09-16 13 views
6

Ho un TreeView che assomiglia a questo:Che cos'è un XAML TreeView idiomatico con i raggruppamenti CollectionViewGroup?

<TreeView Grid.Row="1" x:Name="InspectionResultsTreeView" 
      ItemsSource="{Binding Source={StaticResource InspectionTypeGroupViewSource}, Path=Groups}" 
      ItemTemplate="{StaticResource InspectionTypeGroupsTemplate}"> 
</TreeView> 

Il ItemsSource è una risorsa a chiave che va sotto il nome di InspectionTypeGroupViewSource:

<CollectionViewSource x:Key="InspectionTypeGroupViewSource" Source="{Binding Results}"> 
    <CollectionViewSource.GroupDescriptions> 
     <PropertyGroupDescription PropertyName="Inspection.InspectionType" /> 
     <PropertyGroupDescription PropertyName="Inspection" /> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 

Il ruolo di questa piccola cosa è quello di prendere il ViewModel di Results proprietà:

private ObservableCollection<ICodeInspectionResult> _results; 

public ObservableCollection<ICodeInspectionResult> Results 
{ 
    get { return _results; } 
    set { _results = value; OnPropertyChanged(); } 
} 

... e di gruppo su due livelli - prima per InspectionType, quindi per Inspection - il risultato è una gerarchia a 3 livelli con tipi di ispezione, ispezioni e risultati di ispezione individuali. A questo punto uno screenshot potrebbe aiutare la visualizzazione immagino:

Rubberduck 2.0 Code Inspections toolwindow

Così, il ItemTemplate del InspectionResultsTreeView è un'altra risorsa a chiave, con il nome di InspectionTypeGroupsTemplate - che è il audaci "tipo di ispezione" elementi:

<HierarchicalDataTemplate x:Key="InspectionTypeGroupsTemplate" 
          DataType="{x:Type CollectionViewGroup}" 
          ItemsSource="{Binding Items}" 
          ItemTemplate="{StaticResource InspectionGroupsTemplate}"> 

    <StackPanel Orientation="Horizontal"> 
     <TextBlock VerticalAlignment="Center" 
        Text="{Binding Name}" 
        FontWeight="Bold" 
        TextWrapping="NoWrap"/> 
     <TextBlock Margin="4,0,4,0" 
        VerticalAlignment="Center" 
        Text="{Binding ItemCount, StringFormat=({0})}" 
        TextWrapping="NoWrap"/> 
    </StackPanel> 
</HierarchicalDataTemplate> 

E la ItemTemplate di tale modello è un InspectionGroupsTemplate - che è i singoli controlli, con le icone "gravità":

<HierarchicalDataTemplate x:Key="InspectionGroupsTemplate" 
          DataType="{x:Type CollectionViewGroup}" 
          ItemsSource="{Binding Items}" 
          ItemTemplate="{StaticResource InspectionResultTemplate}"> 

    <StackPanel Orientation="Horizontal"> 
     <Image Style="{StaticResource IconStyle}" 
       Source="{Binding Name, Converter={StaticResource InspectionIconConverter}}" 
       VerticalAlignment="Center" /> 
     <TextBlock Margin="4" 
        VerticalAlignment="Center" 
        Text="{Binding Name, Converter={StaticResource InspectionDescriptionConverter}}" 
        TextWrapping="NoWrap"/> 
     <TextBlock Margin="0,4,0,4" 
        VerticalAlignment="Center" 
        Text="{Binding ItemCount, StringFormat=({0})}" 
        TextWrapping="NoWrap"/> 
    </StackPanel> 
</HierarchicalDataTemplate> 

Infine, l'ItemTemplate di questo raggruppamento è un InspectionResultTemplate, che è per ogni singolo risultato di controllo:

<DataTemplate x:Key="InspectionResultTemplate" 
       DataType="{x:Type inspections:ICodeInspectionResult}"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock VerticalAlignment="Center" 
        Margin="4" 
        Text="{Binding Name}" 
        TextWrapping="NoWrap"/> 
    </StackPanel> 
</DataTemplate> 

L'interfaccia ICodeInspectionResult ha una proprietà string Name che sto usando qui; questo Name è diverso da Name utilizzato nei livelli di raggruppamento, dove è un - il tipo sottostante di quello Name è quello del raggruppamento, quindi il livello 1 è un InspectionType e il livello 2 è Inspection.

Il problema è che sto usando più convertitori di quelli di cui avrei bisogno, per convertire questo object Name e accedere ai membri che ho bisogno di accedere e visualizzare ... ma poi, ho bisogno di visualizzare il numero di articoli in ogni raggruppamento in modo che il DataType dovrebbe essere un CollectionViewGroup ... giusto?

Come posso fare questo senza ricorrere a un convertitore per tutto ciò che deve essere visualizzato? Come si può fare questo ? Ogni esercitazione TreeView/CollectionViewGroup che ho trovato è stata un'implementazione banale.

risposta

1

Hai riscontrato il problema iconico con XAML: è quasi anche strutturato.

Il più soluzione idiomatic sta scrivendo un controllo utente WPF personalizzato. (Come e ciò che includi in esso è su di te.) L'obiettivo del controllo utente di WPF è eliminare il markup e la logica XAML duplicati.Puoi includere il tuo Converter nel controllo utente ed eliminare i convertitori dal tuo controllo principale.

Ci sono molti tutorial sulla creazione di oggetti UserControl in WPF, quindi non entrerò nei dettagli qui.


Per quanto riguarda la questione Converter: questo è quasi il modo più idiomatica. Ogni convertitore è riutilizzabile e si concentra solo su un tipo di sorgente. Non c'è molto altro da fare al riguardo, tranne considerare la possibilità di unire convertitori che supportano lo stesso tipo di sorgente. (C'è un motivo per cui il convertitore ha un parametro Type targetType e uno object parameter.)