NobsterTheLobster / Xamarin.Forms.GridView

GridView for xamarin forms
MIT License
60 stars 10 forks source link

The item do not display if the height is set after loading (iOS) #9

Open MatthieuNarcisi opened 7 years ago

MatthieuNarcisi commented 7 years ago

It is me again.

So here is the issue I was facing : I have a grid view in a page declared in XAML. Like this :

<controls:GridView
    x:Name="PicturesGrid"
    Grid.RowSpan="2"
    Grid.ColumnSpan="3"
    Margin="-2,0,-2,0"
    AutomationId="PicturesGrid"
    GridItemTapped="OnPictureTapped"
    HasUnevenRows="True"
    IsGroupingEnabled="False"
    ItemsSource="{Binding Pictures}"
    TappedCommand="{Binding ToggleSelectionCommand}">

My issue is that I want square items (to display a picture gallery). So I set the RowHeight and MinItemWidth in the code behind in the OnAppearing of my page to be sure to have the measurement of the page updated. This gives me something like this :

protected override void OnAppearing()
{
    this.PicturesGrid.MinItemWidth = Math.Floor(this.Width / 3);
    this.PicturesGrid.RowHeight = (int)this.PicturesGrid.MinItemWidth;
}

My issue is that the first time I navigate to the page, nothing appeared. The RowHeight not being set when the GridView was initialized. So the ItemSize was set to 0 and thus, no element was displayed. Then if I navigated away and came back to the page, the items were displaying right.

So I made a change to the code to be sure that the ItemSize was updated when the RowHeight property was changed :

Created the UpdateItemSize method which does the same thing that was done in ElementSizeChanged :

private void UpdateItemSize()
{
    //Unbox the grid view.
    var gridView = this.Element;

    //Work out how many items can fit.
    var canfit = (int)Math.Max(1, Math.Floor(gridView.Width / gridView.MinItemWidth));

    //Stretch the width to fill row.
    var actualWidth = gridView.Width / canfit;

    //Set the item size accordingly.
    _gridCollectionView.ItemSize = new CoreGraphics.CGSize(actualWidth, (float)gridView.RowHeight);
}

And the method is now called where the ItemSize needs to be called (OnElementChanged, ElementSizeChanged and OnElementPropertyChanged). The new OnElementPropertyChanged method:

protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);
    var gridView = sender as GridView;

    if (e.PropertyName == "ItemsSource")
    {
        if (gridView.ItemsSource != null)
        {
            _gridCollectionView.DataSource = DataSource;
            ReloadData();
            ScrollToInitialIndex();
        }
    }

    if (e.PropertyName == "RowHeight")
    {
        this.UpdateItemSize();
    }
}

So now, each time the RowHeight is changed, the ItemSize is changed accordingly.

Hope that helps.

Cheers, and thank you again for your work !