2009-05-22 8 views
8

a veces WPF es demasiado complejo para mí. Tengo mi "Ventana1" sosteniendo una colección de "Grupos". "Grupo" es una clase con una colección de "Persona" s. Al final esto debería ser una lista de contactos. Lo que simplemente quiero hacer es mostrar los grupos con su persona en un ListBox, donde el nombre del grupo de los grupos de la lista es igual a la propiedad del nombre de mi clase "Grupos".WPF: Colección de enlace con colección en un ListBox con grupos

He intentado con un CollectionViewSource vinculado a la "Colección". Los grupos se muestran correctos, pero los elementos de la lista son iguales a los nombres de los grupos. Entonces cada grupo tiene solo un elemento: el nombre de su grupo.

Muchos ejemplos aquí muestran la agrupación de elementos con una sola colección. Lo que puedo hacer es establecer el nombre del grupo como Propiedad de "Persona". Pero luego no puedo contar (y eso es realmente necesario): - cuántas personas hay en cada grupo - cuántas de esas personas tienen el "Estado" "En línea".

Utilizo linq en la clase "Grupo" para contar eso. Gracias por cualquier consejo que me ayude a comenzar.

Respuesta

21

Bueno, no estoy seguro si esto es lo que quiere lograr, pero aquí hay una manera que usted puede probar:

Suponiendo sus clases son como éstos:

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

Usted puede establecer ListBox.ItemTemplate como otro cuadro de lista se unen a Contactos propiedad, como:

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

Usted tiene el estilo del interior listaB buey un poco.

Editar: Otra solución mediante el uso de 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

Esto es bastante útil e igual a mi solución anterior, donde tenía un expansor por grupo y un ListBox para los contactos. El problema aquí es que puede seleccionar una persona por lista, pero supongo que puede hacerlo con una. Intento copiar la interfaz de usuario de la lista de contactos de Windows Live Messenger 2009. Creo que usaron solo un ListBox y un Expander como ControlTemplate para el grupo. Pero también supongo que definieron al grupo como propiedad. Pero realmente no sé cómo pueden contar las personas en línea. Por cierto, tienes razón con tus clases. –

+0

¿Por qué no usa el control TreeView para mostrar datos jerárquicos? – idursun

+0

¡Tienes toda la razón! Creo que eso resolvería mi problema con seguridad. No tengo respuesta para el "por qué". No he usado mucho el control TreeView. Pero esto sería lo mejor para mi problema. ¡Gracias! –

8

Si usted tiene una copia de Programming WPF, salta a la página 221. Si no voy a resumir (en mi clase de manera inepta)

En primer lugar, no es necesario agrupar los objetos Persona manualmente.

Si cada persona objeto tiene una propiedad de Grupo,

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

Todos los controles que se derivan de ItemsControl puede mostrar los elementos agrupados, por lo

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

También puede definir una costumbre GroupStyle y especifique la GroupStyle .HeaderTemplate para definir un nuevo DataTemplate que muestra atributos personalizados como 'algún PropertyValue (Count)' - Enlaza el un TextBlock al {Binding SomeProperty} y el otro al {Binding ItemCount}

HTH

+0

Gracias, primero. El objeto Mi persona NO tiene una propiedad de grupo, aún. Me gustaría evitarlo No entendí cómo puedo manejar el conteo (solo la lógica, el hecho con TextBlock es claro). Este es un código, si lo puede ayudar. enum {Onlinestatus línea, sin conexión} class Persona {// La cabecera de cada grupo debe contar // cuántos persona existe con Onlinestatus "en línea". public Online Status Status {get; conjunto; } } clase Grupo { public List Personas = new List (); } clase Window1 { public List Groups = new List ; } –

+0

+1, '{Binding ItemCount}' ¡Era la respuesta que necesitaba! ¡GRACIAS! – Dom

Cuestiones relacionadas