WPF:使用集合将集合绑定到带有组的列表框

时间:2022-09-16 07:34:41

sometimes WPF is too complex for me. I've got my "Window1" holding a collection of "Group"s. "Group" is a class with a collection of "Person"s. In the end this should be a contact list. What I simply want to do is to show the groups with its person in a ListBox, where the group name of the list groups equals the Name Property of my class "Groups".

有时候WPF对我来说太复杂了。我的“Window1”包含了一组“组”。“Group”是一个集合了“Person”的类。最后,这应该是一个联系人列表。我想做的是在列表框中显示组,列表组的组名等于类“组”的名称属性。

I've tried with a CollectionViewSource bound to the "Collection". The groups are shown correct, but the items of the list are equal to the group names. So each group has only one item: its group name.

我尝试了一个与“Collection”绑定的CollectionViewSource。组显示正确,但是列表项与组名称相同。所以每个组只有一个项目:它的组名。

Many examples here show the grouping of items with only one collection. What I can do is to set the group name as Property of "Person". But then I can't count (and that is really neccessary): - how many persons are in each group - how many of that persons have the "Status" "Online".

这里的许多示例显示了只包含一个集合的项的分组。我可以做的是将组名设置为“Person”的属性。但是我不能数(这确实是必要的):-每个小组有多少人-有多少人有“地位”“在线”。

I use linq in the "Group" class to count that. Thanks for any advice helping me to get started.

我在“组”类中使用linq来计数。谢谢你给我的建议。

2 个解决方案

#1


21  

Well, I am not sure if this is what you want achieve but here is a way that you can try:

我不确定这是否是你想要的结果,但这里有一个方法你可以尝试:

Assuming your classes are like these:

假设你的课程是这样的:

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

You can set ListBox.ItemTemplate as another ListBox bind to Contacts property, like:

你可以设置列表框。ItemTemplate作为另一个列表框绑定到联系人属性,比如:

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

You have to style the inner listbox a little bit.

你需要对内部列表框进行一点样式化。

Edit: Another solution by using TreeView

编辑:使用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>

#2


8  

If you have a copy of Programming WPF, jump to Page 221. If not I'll summarize (in my inept sort of way)

如果您有一个编程WPF的副本,请跳转到第221页。如果不是的话,我就总结一下

First you don't need to manually group the Person objects.

首先,不需要手动对Person对象进行分组。

If each Person object has a Group property,

如果每个Person对象具有组属性,

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

All controls that derive from ItemsControl can display grouped items, so

所有从ItemsControl派生的控件都可以显示分组项,因此

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

You can also define a custom GroupStyle and specify the GroupStyle.HeaderTemplate to define a new DataTemplate that shows custom attributes like 'some PropertyValue (Count)' - Bind the one TextBlock to {Binding SomeProperty} and the other to {Binding ItemCount}

您还可以定义自定义的GroupStyle并指定GroupStyle。HeaderTemplate定义一个新的DataTemplate,该面板显示自定义属性,如“some PropertyValue (Count)”——将一个TextBlock绑定到{Binding SomeProperty},另一个绑定到{Binding ItemCount}

HTH

HTH

#1


21  

Well, I am not sure if this is what you want achieve but here is a way that you can try:

我不确定这是否是你想要的结果,但这里有一个方法你可以尝试:

Assuming your classes are like these:

假设你的课程是这样的:

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

You can set ListBox.ItemTemplate as another ListBox bind to Contacts property, like:

你可以设置列表框。ItemTemplate作为另一个列表框绑定到联系人属性,比如:

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

You have to style the inner listbox a little bit.

你需要对内部列表框进行一点样式化。

Edit: Another solution by using TreeView

编辑:使用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>

#2


8  

If you have a copy of Programming WPF, jump to Page 221. If not I'll summarize (in my inept sort of way)

如果您有一个编程WPF的副本,请跳转到第221页。如果不是的话,我就总结一下

First you don't need to manually group the Person objects.

首先,不需要手动对Person对象进行分组。

If each Person object has a Group property,

如果每个Person对象具有组属性,

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

All controls that derive from ItemsControl can display grouped items, so

所有从ItemsControl派生的控件都可以显示分组项,因此

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

You can also define a custom GroupStyle and specify the GroupStyle.HeaderTemplate to define a new DataTemplate that shows custom attributes like 'some PropertyValue (Count)' - Bind the one TextBlock to {Binding SomeProperty} and the other to {Binding ItemCount}

您还可以定义自定义的GroupStyle并指定GroupStyle。HeaderTemplate定义一个新的DataTemplate,该面板显示自定义属性,如“some PropertyValue (Count)”——将一个TextBlock绑定到{Binding SomeProperty},另一个绑定到{Binding ItemCount}

HTH

HTH