How to create variable sized group panels to fit t

2019-03-31 14:21发布

问题:

The problem I'm having is the grouped grid view sizes all of its groups to the size of the first group as in the screenshot below:

I need the groups to have different widths to accomodate their children. In this case the second group should be wider and the third group should be narrower.

The code for the test app I wrote is as below:

XAML (MainPage.xaml)

<Page x:Class="GroupingBugTest.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="using:GroupingBugTest"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d">
<Page.Resources>
    <CollectionViewSource x:Name="GroupedCollectionViewSource" IsSourceGrouped="True" />
</Page.Resources>

<Grid Margin="100" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <GridView x:Name="GroupingGridView"
              ItemsSource="{Binding Source={StaticResource GroupedCollectionViewSource}}"
              SelectionMode="None">
        <GridView.ItemsPanel>
            <ItemsPanelTemplate>
                <VariableSizedWrapGrid Margin="20"
                                       Background="MidnightBlue"
                                       Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </GridView.ItemsPanel>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock FontSize="24"
                                   Foreground="White"
                                   Text="{Binding Key}" />
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>

                <GroupStyle.Panel>
                    <ItemsPanelTemplate>
                        <VariableSizedWrapGrid Margin="20"
                                               Background="CornflowerBlue"
                                               Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </GroupStyle.Panel>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>
</Grid>

Code behind (MainPage.xaml.cs)

using System.Collections.Generic;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace GroupingBugTest
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        PopulateGroupedCollectionViewSource();
    }

    private void PopulateGroupedCollectionViewSource()
    {
        List<GroupInfoList<string>> groupedCollection = new List<GroupInfoList<string>>();

        var firstGroup = new GroupInfoList<string>() { Key = "FIRST GROUP (5 items)" };
        var secondGroup = new GroupInfoList<string>() { Key = "SECOND GROUP (10 items)" };
        var thirdGroup = new GroupInfoList<string>() { Key = "THIRD GROUP (2 items)" };

        for (int i = 1; i <= 10; i++)
        {
            if (i <= 5) //add 5 items to first group
            {
                firstGroup.Add(i.ToString());
            }

            secondGroup.Add(i.ToString()); //add 10 items to second group

            if (i <= 2) //add 2 items to third group
            {
                thirdGroup.Add(i.ToString());
            }
        }

        groupedCollection.Add(firstGroup);
        groupedCollection.Add(secondGroup);
        groupedCollection.Add(thirdGroup);

        GroupedCollectionViewSource.Source = groupedCollection;
    }
}

//Taken from Microsoft Windows 8 code samples
public class GroupInfoList<T> : List<object>
{
    public object Key { get; set; }

    public new IEnumerator<object> GetEnumerator()
    {
        return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
    }
}
}

回答1:

First of all, don't use List, use ObservableCollection. This way, the CollectionViewSource will respond to the changes in the Collection.

Second, your GridView.ItemsPanel should not be a VariableSizedWrapGrid, but likely some kind of StackPanel, such as a VirtualizingStackPanel.

Note: The GroupStyle.Panel should be a VariableSizedWrapGrid, which you are currently doing correctly.