ItemsControl (WrapPanel) 分组应该拆分 GroupItems

ItemsControl (WrapPanel) Grouping should split GroupItems

我有一个带有 WrapPanel 作为 ItemsHost 和多个分组的 ItemsControl。 使用以下模板到目前为止:

<GroupStyle.ContainerStyle>
   <Style TargetType="GroupItem">
      <Setter Property="Template">
         <Setter.Value>
            <ControlTemplate TargetType="GroupItem">
               <Grid>
                  <Grid.RowDefinitions>
                     <RowDefinition Height="Auto" />
                     <RowDefinition Height="*" />
                  </Grid.RowDefinitions>
                  <ContentPresenter Grid.Row="0" x:Name="PART_Header" Content="{TemplateBinding Content}" />
                  <ItemsPresenter Grid.Row="1" />
               </Grid>
            </ControlTemplate> 
         </Setter.Value>
      </Setter>
   </Style>
</GroupStyle.ContainerStyle>
<GroupStyle.Panel>
   <ItemsPanelTemplate>
      <WrapPanel IsItemsHost="True" Orientation="Vertical" />
   </ItemsPanelTemplate>
</GroupStyle.Panel>

现在我遇到了一个问题,即每个组都会开始一个新的列,为什么我希望它在最后一个 GroupItem 的下方继续并在 GroupItem 的中间而不是在开头换行。

它应该类似于 Windows 8 Apps 概览(如果您转到概览,则不是起始页)

这可能吗?

我在 ViewModel 中解决了这个问题。我将 GroupItem 添加到 ObservableCollection 中,其样式类似于(可扩展的)GroupHeader。 比我为 GroupHeader 添加了一个单独的 DataTemplate,它在组上设置了一个 IsCollapsed 属性。所有项目现在都有对父组的引用,并将可见性绑定到父组的 IsCollapsed 属性。

遗憾的是我无法使用 CollectionViewSource 实现此目的。

这是XAML:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.DataContext>
        <local:ViewModel/>  
   </ItemsControl.DataContext>
   <ItemsControl.Resources>
       <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
       <DataTemplate DataType="{x:Type local:GroupViewModel}">
           <StackPanel>
               <CheckBox IsChecked="{Binding IsExtended}" />
               <!--Restyle to look like a extender-->
           </StackPanel>
       </DataTemplate>
       <DataTemplate DataType="{x:Type local:ItemViewModel}">
           <TextBlock Text="{Binding Name}" 
               Visibility="{Binding Group.IsExtended, Converter={StaticResource BooleanToVisibilityConverter}}"/>
       </DataTemplate>
   </ItemsControl.Resources>
</ItemsControl>

这是视图模型:

public class ViewModel
{
    public ViewModel()
    {
        //Some Test data
        GroupViewModel group1 = new GroupViewModel("Group1");
        GroupViewModel group2 = new GroupViewModel("Group2");

        this.Items = new ObservableCollection<object>(new[]
        {
            new ItemViewModel("Item1", group1),
            new ItemViewModel("Item2", group1),
            new ItemViewModel("Item3", group2),
            new ItemViewModel("Item4", group2)
        });

        string groupName = string.Empty;
        foreach (ItemViewModel item in this.Items.ToArray())
        {
            //Insert Group headers
            if (item.Group.Name != groupName)
            {
                groupName = item.Group.Name;
                this.Items.Insert(this.Items.IndexOf(item), item.Group);
            }
        }
    }

    public ObservableCollection<object> Items { get; }
}


public class GroupViewModel : ViewModelBase
{
    private bool isExtended = true;

    public GroupViewModel(string name)
    {
        this.Name = name;
    }

    public string Name { get; }

    public bool IsExtended
    {
        get { return this.isExtended; }
        set { this.SetProperty(ref this.isExtended, value); }
    }
}

public class ItemViewModel
{
    public ItemViewModel(string name, GroupViewModel group)
    {
        this.Name = name;
        this.Group = group;
    }

    public string Name { get; }
    public GroupViewModel Group { get; }
}

您不能直接进行这种包装,因为组在一个面板中,而每个组中的项目在各自的面板中。

您有两个选择:

  • 使用视图模型和数据模板的组合来模拟分组。 ItemsSource 不会分组 CollectionView,只是简单的 collection,但项目将包含组名称。在 DataTemplate 中,您将为每个组中的第一个项目显示组 Header。

  • 创建您自己的控件,它会立即将 children 排列成组。相当多的工作,但更好的可重用性。我相信这就是 WinRT GridView 和 ListView 分组的工作方式。也许你可以在 WPF

  • 中找到类似的第 3 方控件