2009-05-22 15 views
8

a volte WPF è troppo complesso per me. Ho il mio "Window1" contenente una collezione di "Group". "Gruppo" è una classe con una raccolta di "Persone". Alla fine questo dovrebbe essere un elenco di contatti. Quello che voglio semplicemente fare è mostrare i gruppi con la sua persona in un ListBox, dove il nome del gruppo dei gruppi di liste è uguale alla proprietà Name della mia classe "Groups".WPF: associa raccolta con raccolta a un ListBox con gruppi

Ho provato con un oggetto CollectionViewSource associato alla "Raccolta". I gruppi sono visualizzati correttamente, ma gli elementi della lista sono uguali ai nomi dei gruppi. Quindi ogni gruppo ha un solo oggetto: il suo nome di gruppo.

Molti esempi qui mostrano il raggruppamento di articoli con una sola raccolta. Quello che posso fare è impostare il nome del gruppo come proprietà di "Persona". Ma poi non posso contare (e questo è davvero necessario): - quante persone ci sono in ogni gruppo - quante di quelle persone hanno lo "Stato" "Online".

Io uso linq nella classe "Gruppo" per conteggiare. Grazie per qualsiasi consiglio che mi aiuti a iniziare.

risposta

21

Beh, io non sono sicuro se questo è ciò che si vuole raggiungere, ma qui è un modo che si può provare:

Supponendo che le vostre classi sono come questi:

public class Group 
{ 
    public string Name { get; set; } 
    public List<Contact> Contacts { get; set; } 
} 

public class Contact 
{ 
    public string Name { get; set; } 
    public bool IsOnline { get; set; } 
} 

È può impostare ListBox.ItemTemplate come un altro ListBox si legano a contatti proprietà, come:

<CollectionViewSource x:Key="groups" Source="{Binding}" > 
    <CollectionViewSource.GroupDescriptions> 
     <PropertyGroupDescription PropertyName="Name" /> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 

<DataTemplate x:Key="groupTemplate" DataType="Group"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="{Binding Name}" /> 
    </StackPanel> 
</DataTemplate> 

<ListBox ItemsSource="{Binding Source={StaticResource groups}}"> 
    <ListBox.GroupStyle> 
     <GroupStyle HeaderTemplate="{StaticResource groupTemplate}" /> 
    </ListBox.GroupStyle> 
    <ListBox.ItemTemplate> 
     <DataTemplate DataType="Contact"> 
      <ListBox ItemsSource="{Binding Contacts}"> 
       <ListBox.ItemTemplate> 
        <DataTemplate DataType="Contact"> 
         <TextBlock Text="{Binding Name}" /> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

bisogna per lo stile della elencoB interna un po 'di bue

Edit: Un'altra soluzione utilizzando TreeView

<DataTemplate DataType="Contact"> 
    <TextBlock Text="{Binding Name}" /> 
</DataTemplate> 

<TreeView ItemsSource="{Binding Source={StaticResource groups}}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding Contacts}"> 
      <TextBlock Text="{Binding Name}" /> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 
+0

Questo è utile ed è uguale alla mia vecchia soluzione, dove avevo un Expander per gruppo e un ListBox per i Contatti. Il problema qui è che puoi selezionare una persona per lista, ma suppongo che tu possa farcela con una. Provo a copiare l'interfaccia utente dell'elenco contatti di Windows Live Messenger 2009. Penso che abbiano usato solo un ListBox e un Expander come ControlTemplate per il gruppo. Ma suppongo anche che abbiano definito il gruppo come proprietà. Ma davvero non lo so, come possono contare le persone online. A proposito, hai ragione con le tue lezioni. –

+0

Perché non si utilizza il controllo TreeView per la visualizzazione di dati gerarchici? – idursun

+0

Hai assolutamente ragione! Penso che risolverebbe sicuramente il mio problema. Non ho una risposta per il "perché". Non ho usato molto il controllo TreeView. Ma questo sarebbe il migliore per il mio problema. Grazie! –

8

Se si dispone di una copia di Programming WPF, passare a pagina 221. Se non cercherò di riassumere (nel mio sorta inetto di passaggio)

In primo luogo non è necessario per raggruppare gli oggetti Person manualmente.

Se ogni oggetto Person ha una proprietà del Gruppo,

People people = // retrieve the List<Person> somehow 
ICollectionView view = CollectionViewSource.GetDefaultView(people); 
view.GroupDescriptions.Add(new PropertyGroupDescription("Group")); 

Tutti i controlli che derivano da ItemsControl in grado di visualizzare gli elementi raggruppati, in modo

// the XAML 
<ListBox ... ItemsSource={Binding}> 
    <ListBox.GroupStyle> 
    <x:Static Member="GroupStyle.Default" /> 
    </ListBox.GroupStyle> 
</ListBox> 

È inoltre possibile definire un costume GroupStyle e specificare il GroupStyle .HeaderTemplate per definire un nuovo DataTemplate che mostra attributi personalizzati come 'some PropertyValue (Count)' - Lega uno TextBlock a {Binding SomeProperty} e l'altro a {Binding ItemCount}

HTH

+0

Grazie, prima. L'oggetto My Person NON ha ancora una proprietà di gruppo. Mi piacerebbe evitarlo. Non ho capito come gestire il conteggio (solo la logica, il fatto con TextBlock è chiaro). Ecco un codice, se può aiutarti. enum OnlineStatus {ONLINE, OFFLINE} classe Persona { // L'intestazione di ogni gruppo deve conteggiare // quante persone esiste con OnlineStatus "Online". Stato OnlineStatus pubblico {get; impostato; } } gruppo classe { elenco pubblico persone = nuovo elenco (); } classe Window1 { elenco pubblico Gruppi = nuova lista ; } –

+0

+1, '{Binding ItemCount}' era la risposta di cui avevo bisogno! GRAZIE! – Dom