我可以使用 WrapPanel 来组织 ListView 组 headers 吗?

Can I use a WrapPanel to organize ListView group headers?

我希望能够使用 WrapPanel 按组 header 而不是按项目进行包装。

我已经为绑定到 ObservableCollection studentlist 的 ListView 实现了以下 ICollectionView view

        view = CollectionViewSource.GetDefaultView(studentlist);
        view.GroupDescriptions.Add(new PropertyGroupDescription("sectionoutput"));
        view.SortDescriptions.Add(new SortDescription("sectionoutput", ListSortDirection.Ascending));
        view.SortDescriptions.Add(new SortDescription("displayname", ListSortDirection.Ascending));

XAML 包含样式资源,用于设置群组模板 header:

    <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                        <Expander Header="{Binding Name}" IsExpanded="{Binding Name, Mode=OneWay, Converter={StaticResource expanderconverter}}">
                            <ItemsPresenter />
                        </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

此样式用作 ListView 的组样式:

    <ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">            
        <ListView.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
        </ListView.GroupStyle>
...
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding displayname}">
                </TextBlock>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

照原样,代码显示了一个垂直列表,学生姓名按 header 分组,列出了他们的部分编号。但是我想在水平方向上按顺序列出组。

我知道我可以使用 WrapPanel 组织 ListView 中的项目:

        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" ItemWidth="150">                        
                </WrapPanel>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>

但是这段代码只是并排显示一组中的学生,而不是并排显示组本身。我想做的是将组本身水平包裹起来。我试过在style资源中实现一个wrap panel,但是没有成功,一直想知道有没有办法按组换行。

我认为可以通过切换到 TreeView 并将组转换为项目来实现此目的。但如果可能的话,我更愿意使用 ListView,因为我的程序实现了一个将 ListView 作为参数的 class。

假设有一个 ViewModel,它是下面发布的 XAML 的 DataContext,它包含一个名为 GroupsViewModelObservableCollection<GroupViewModel>

GroupViewModel 仅仅有一个名为 GroupName 的 属性,这是要显示的组的名称,它有一个 属性 ObservableCollection<StudentViewModel>

StudentViewModel 有 属性 displayName 来显示学生的姓名。

这么说,通过使用一个Expander和2个嵌套的ListBox就可以得到你所要求的,就像下面的代码:

<ListBox ItemsSource="{Binding GroupsViewModel}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid>
            <Expander HorizontalAlignment="Left" IsExpanded="True" Header="{Binding GroupName}">
                <ListBox ItemsSource="{Binding StudentViewModel}" HorizontalAlignment="Left">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding displayname}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Vertical"></StackPanel>
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>
                </ListBox>
            </Expander>
        </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"></StackPanel>
    </ItemsPanelTemplate>
</ListBox.ItemsPanel>

GroupStyle 有一个 Panel 属性,您可以将其设置为 ItemsPanelTemplateWrapPanel:

<ListView.GroupStyle>
    <GroupStyle ContainerStyle="{StaticResource ContainerStyle}">
        <GroupStyle.Panel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </GroupStyle.Panel>
    </GroupStyle>
</ListView.GroupStyle>