XAML grouped GridView/Semantic Zoom not displaying

2020-07-23 06:13发布

问题:

I'm attempting to use the XAML C# Grouped GridView sample to make my SemanticZoom work in a XAML C# Windows 8 app. The problem is, for some reason it's displaying the correct header (the category, in this case), but it's not showing all the items under the header (it's only showing one for each, when I have up to 6 items in some of them).

Here's the SemanticZoom's XAML code (note that I left out the ZoomedOutView for brevity, and since it's working perfectly):

<SemanticZoom x:Name="boardZoom" Height="626" Margin="10,132,10,0" VerticalAlignment="Top">
    <SemanticZoom.ZoomedInView>
        <GridView IsSwipeEnabled="True" x:Name="ItemsGridView" Tapped="Tapped" ItemsSource="{Binding Source={StaticResource cvs2}}" SelectionChanged="selChanged">
            <GridView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="10,10,0,0" 
                    HorizontalAlignment="Left" VerticalAlignment="Stretch">
                        <Image Source="{Binding Thumbnail}"></Image>                                
                       <TextBlock Text="{Binding Title}" TextWrapping="Wrap" Width="500"
                            FontFamily="Global User Interface" FontSize="40" VerticalAlignment="Top" />                                
                        <TextBlock Text="{Binding pinNumber}" x:Name="PinNum" Visibility="Collapsed"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </GridView.ItemTemplate>         
            <GridView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                           <TextBlock Text='{Binding Key}' Foreground="White" Margin="5" FontSize="20" FontFamily="Segoe UI Light" />
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="GroupItem">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="GroupItem">
                                        <StackPanel Orientation="Vertical">
                                            <ContentPresenter Content="{TemplateBinding Content}" />
                                            <ItemsControl x:Name="ItemsControl" ItemsSource="{Binding GroupItems}" />
                                        </StackPanel>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                    <GroupStyle.Panel>
                        <ItemsPanelTemplate>
                            <VariableSizedWrapGrid Orientation="Vertical" MaximumRowsOrColumns="5" />
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                </GroupStyle>
            </GridView.GroupStyle>
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapGrid Orientation="Vertical" MaximumRowsOrColumns="1" />
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>
    </SemanticZoom.ZoomedInView>

and the Refresh() C# function that's called when the app is started up:

System.Collections.ObjectModel.ObservableCollection<SemanticZoomed> finalSource = new System.Collections.ObjectModel.ObservableCollection<SemanticZoomed>();
public async Task<bool> Refresh()
{
    var Pins = await pinTable.ReadAsync(); //pinTable is an Azure Mobile Services table
    List<string> categoriesMixed = new List<string>();
    if (Pins.ToArray().Length < 1)
    {
        //adds a new "Welcome" pin to the table, taken out for brevity
    }
    foreach (pin nowPin in Pins)
    {
        SemanticZoomed toAdd = new SemanticZoomed();
        toAdd.Category = nowPin.category;
        toAdd.pinNumber = nowPin.Id.ToString();
        toAdd.Title = nowPin.name;
        categoriesMixed.Add(nowPin.category);
        finalSource.Add(toAdd);
    }

    List<GroupPinList<object>> groups = new List<GroupPinList<object>>();

    var query = from nowPin in finalSource
        orderby ((SemanticZoomed)nowPin).Category
                group nowPin by ((SemanticZoomed)nowPin).Category into g
                select new { GroupName = g.Key, Items = g };
    foreach (var g in query)
    {
        GroupPinList<object> info = new GroupPinList<object>();
        info.Key = g.GroupName;
        foreach (var item in g.Items)
        {
           info.Add(item);
        }
        groups.Add(info);
    }
    cvs2.Source = groups;
    (boardZoom.ZoomedOutView as ListViewBase).ItemsSource = cvs2.View.CollectionGroups;
    return true;
}

And here are a few screenshots of what the groups variable looks like, and what the resulting SemanticZoom shows:

the groups variable:

the "Welcome" category in the groups variable (it correctly shows its 6 items, and also the error "Cannot fetch the value of field 'imgSrc' because information about the containing class is unavailable" next to imgSrc, which disappears in cvs2 below):

cvs2 (it shows the 6 different items under the Welcome category):

and finally, what it ends up displaying:

I'm at a loss as to where those other pins in the Welcome category went. Is there something in the XAML code that I'm missing? Any help would be much appreciated :)

回答1:

I think I know where's the problem - this happens if you are adding items to the GridView programatically group after group. What happens here is when you add the first group with n items to the GridView source, then number n is kept and for each group added afterwards it shows no more than n items, even though there is more items.

So if you have 5 groups in collection with 2,4,1,5,3 items, you assign empty ObservableCollection as the ItemSource of the GridView and then you add in foreach these groups into the ObservableCollection, you will see only 2,2,1,2,2 items in each group.

I don't know why this is happening, if it's feature or a bug, but you can solve it either by loading the ObservableCollection first and then assigning it to the GridView as a source, or you can use some kind of converter, that will return for each group same number of items. For groups with lesser number you then add fake empty items and hide them using different DataTemplate.

Edit: I've just noticed you are already adding the collection at once, so the problem is probably elsewhere. Maybe the root you your issue is this in ItemsPanel?

MaximumRowsOrColumns="1"


回答2:

I have the same problem . And this at resolved the pb .

In the SemanticZoom.ZoomedInView replace

<ItemsPanelTemplate>
<WrapGrid Orientation="Vertical" MaximumRowsOrColumns="1" />
</ItemsPanelTemplate>

by

<ItemsPanelTemplate>
         <VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>


回答3:

you need to use stackpanel instead of  WrapGrip in ItemPanelTemplate

<GridView.ItemsPanel>
           <ItemsPanelTemplate>
               <StackPanel Orientation="Horizontal" />
           </ItemsPanelTemplate>
</GridView.ItemsPanel>