How Can You Set Grid Row Height for Android

Viewed 106

I have a content page with two distinct pieces of UI. To manage this, I have a grid with two rows, and the page starts out with one RowDefinition being * and the other being 0. I have a button the user clicks to show the data in the second row, which it does by changing the row height. The code to do this looks like this:

GridLength glHidden = new GridLength(0, GridUnitType.Absolute);
GridLength glShow = new GridLength(1, GridUnitType.Star);

var rows = PageGrid.RowDefinitions;
rows[2].Height = glHidden;  
rows[3].Height = glShow;  

When I run this on iOS it works perfect, exactly as I would expect. When I run it on Android, nothing happens the first time I toggle it. I toggle it back like so (simplified):

rows[2].Height = glShow;  
rows[3].Height = glHidden; 

Since the height of row 2 didn't change when I toggled it the first time, it continues to look like nothing happened. Then when I run the toggle code the third time, it works on Android - row 2 disappears and row 3 shows up.

So...is there some other way in which I should be doing this? Alternatively, I thought about changing the Grid.Row property of the UI I'm trying to toggle, but I can't find a way to do this in the code behind. If that way works uniformly on all operating systems then a pointer to how one might try that would be welcome.

2 Answers

ToolmakerSteve had a solution that worked, but I just wanted to flesh it out a bit in case you are trying to build this yourself. So to begin with, I changed my Grid RowDefinitions to look like this:

<Grid 
        x:Name="PageGrid"
        ColumnDefinitions="*">

        <Grid.RowDefinitions>
            <RowDefinition Height="{Binding ListingsRowHeight}" />
            <RowDefinition Height="{Binding ManageRowHeight}" />
        </Grid.RowDefinitions>
...

I already had a Nuget package reference for CommunityToolkit.Mvvm, so in my code behind I have a using statement for it:

using CommunityToolkit.Mvvm.ComponentModel;

I then added a class to my page's code behind for managing the height (ObservableObject comes from CommunityToolkit.Mvvm):

public partial class MyPageDynamic : ObservableObject
{

    [ObservableProperty]
    GridLength listingsRowHeight;

    [ObservableProperty]
    GridLength manageRowHeight;
}

I then added these fields to my page class:

private static GridLength glHidden = new GridLength(0, GridUnitType.Absolute);
private static GridLength glShow = new GridLength(1, GridUnitType.Star);

MyPageDynamic mpd = new MyPageDynamic() 
{ 
ListingsRowHeight = glShow, 
ManageRowHeight = glHidden 
}; 

Then in the OnNavigatedTo event for the page I set the binding for the Grid to this set of properties:

PageGrid.BindingContext = mpd;

Then when I want to change the row heights, I do it like so:

mpd.ListingsRowHeight = glShow;
mpd.ManageRowHeight = glHidden;

Credit to ToolmakerSteve for the solution.

If you want to use Bindings, the XAML could look like this:

<Grid.RowDefinitions>
    <RowDefinition Height="{Binding Row1Height}" />
    <RowDefinition Height="{Binding Row2Height}" />
</Grid.RowDefinitions>

If you aren't using mvvm, then you can bind to properties of the page itself:

public partial class MyPage
{
    public MyPage()
    {
        InitializeComponent();
        BindingContext = this;
    }
    
    public GridLength Row1Height { get => _row1Height; set => SetProperty(ref _row1Height, value); }
    private GridLength _row1Height = glHidden;
    public GridLength Row2Height { get => _row2Height; set => SetProperty(ref _row2Height, value); }
    private GridLength _row2Height = glShow;
    
    ...
    // Show row 2:
    Row1Height = glShow;
    Row2Height = glHidden;


    // Adapted from https://stackoverflow.com/a/32800248/199364.
    // Typically this is put in a base class.
    protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        // if property value is changing. Handles "null"s.
        if (value == null ? field != null : !value.Equals(field))
        {
            field = value;
            // Some base class must implement INotifyPropertyChanged.
            OnPropertyChanged(propertyName);
        }
    }
}

NOTE: Maui supports "attributes" to make it easier to create properties. Those would simplify the above code. I'm not accustomed to using them yet.

Related