Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UWP GridView ItemHeight based on the biggest item in a row

As discussed already here I've a problem with showing content in a GridView. Based on this article I found out that GridView set the Height property for the items to the height of the first item. The problem for me is that I'd like to have the Height adjusted apdaptive based on the height of the content. So if the second item in a row is the biggest, all items in this row should get the size of the second item.

I've used this code for showing the GridView:

<GridView ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Disabled" Width="1080">
<GridView.ItemTemplate>
    <DataTemplate>
        <ItemsControl ItemsSource="{Binding ListData, Converter={StaticResource DataBindingDebugConverter}}" x:Name="BirthdayListView" HorizontalAlignment="Center" Margin="0,20,0,0">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="&#x1f382;" 
                                    FontSize="16" 
                                    Grid.Column="0"
                                    Margin="0,0,10,10"
                                    FontFamily="Sergoe UI"
                                    Style="{StaticResource BasicTextBlock}"/>
                        <TextBlock Text="{Binding NameString, Converter={StaticResource DataBindingDebugConverter}}" 
                                    Grid.Column="2"
                                    Margin="10,0,0,0"
                                    FontSize="16"
                                    Style="{StaticResource BasicTextBlock}"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
    <Style TargetType="ContentControl">
        <Setter Property="Padding" Value="0"/>
        <Setter Property="Margin" Value="0,20,0,0"/>
        <Setter Property="Width" Value="360" />
        <Setter Property="VerticalContentAlignment" Value="Top" />
    </Style>
</GridView.ItemContainerStyle>
</GridView>

EDIT:

If the calendar entries are on the first entry (Sonntag) everything is fine. enter image description here

If the calendar entries are on the second item (Montag) they are hidden and the ItemHeight is not increasing. enter image description here

like image 537
Christoph Avatar asked Oct 30 '22 12:10

Christoph


1 Answers

Based on this article I found out that GridView set the Height property for the items to the height of the first item.

As you known the row height of GridView depend on the first item not the highest item. So we may need to custom a panel for the GridView's ItemPanel. For example, since the Width of your GridView is fixed value, we can create a CustomPanel as follows:

public class CustomPanel : Panel
{
    private double _maxWidth;
    private double _maxHeight;

    protected override Size ArrangeOverride(Size finalSize)
    {
        var x = 0.0;
        var y = 0.0;
        foreach (var child in Children)
        { 
            if ((_maxWidth + x) > finalSize.Width)
            {
                x = 0;
                y += _maxHeight;
            }
            var newpos = new Rect(x, y, _maxWidth, _maxHeight);
            child.Arrange(newpos);
            x += _maxWidth;
        }
        return finalSize;
    }

    protected override Size MeasureOverride(Size availableSize)
    { 
        foreach (var child in Children)
        {
            child.Measure(availableSize);

            var desirtedwidth = child.DesiredSize.Width;
            if (desirtedwidth > _maxWidth)
                _maxWidth = desirtedwidth;

            var desiredheight = child.DesiredSize.Height;
            if (desiredheight > _maxHeight)
                _maxHeight = desiredheight;
        }            
        var itemperrow = Math.Floor(availableSize.Width / _maxWidth);
        var rows = Math.Ceiling(Children.Count / itemperrow);
        return new Size(itemperrow * _maxWidth,_maxHeight * rows );
    }
}

Then replace the ItemsPanelTemplate of GridView with the CustomPanelin XAML as follows:

<GridView ItemsSource="{Binding}"   Width="1080" >
    <GridView.ItemTemplate> 
     ...  
    </GridView.ItemTemplate>
    <GridView.ItemContainerStyle>
       ... 
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <local:CustomPanel />                  
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
</GridView>
like image 81
Sunteen Wu Avatar answered Nov 15 '22 06:11

Sunteen Wu