Andrei
Andrei

Reputation: 115

ListView doesn't update Cell height in Android and iOS

I'm trying to make an expandable ListView, but facing issues (not working) in Android and iOS (Works in UWP). Tried, many layouts and also tried to make a List inside the list and faced the same result. Android and iOS refuse to update the height of the Cell.

My Xaml

                    <ListView ItemsSource="{Binding groups}"
                          IsGroupingEnabled="true"
                          HasUnevenRows="False"
                          SelectionMode="None"
                          VerticalScrollBarVisibility="Never"  

                           >
                        <ListView.GroupHeaderTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <StackLayout  Padding="5" VerticalOptions="FillAndExpand">
                                        <StackLayout.GestureRecognizers>
                                            <TapGestureRecognizer Command="{Binding HideShowItems}" CommandParameter="{Binding .}" />
                                        </StackLayout.GestureRecognizers>
                                        <Label  Text="{Binding GroupKey}" HorizontalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand"/>
                                    </StackLayout>
                                </ViewCell>
                            </DataTemplate>      
                        </ListView.GroupHeaderTemplate>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                                <ViewCell>
                                    <ViewCell.View>
                                        <Grid Padding="0" HeightRequest="{Binding rowHeight}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="*"/>
                                            </Grid.RowDefinitions>
                                            <BoxView Grid.Row="0" HorizontalOptions="FillAndExpand" 
                                                     BackgroundColor="{Binding BtnColour}"  />
                                        </Grid>
                                    </ViewCell.View>
                                </ViewCell>

                            </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

Command to handle the change

        public Command HideShowItems => new Command(async (sender) =>
        {            
            var dropDown = sender as DropDownMenu;

            foreach(DropDownButton dr in dropDown)
            {
                if (dr.rowHeight > 0)
                {
                    while(dr.rowHeight > 0)
                    {
                        dr.rowHeight = dr.rowHeight - 5;
                        await Task.Delay(5);
                    }

                }
                else
                {
                    while(dr.rowHeight < 40)
                    {
                        dr.rowHeight = dr.rowHeight + 5;
                        await Task.Delay(5);
                    }

                }
            }
        });

Tried quite a few examples found online and none seem to do it.

Still being in the learning stage, it would be helpful if you'd give a feedback when you see anything in the code that could be done better.

Many thanks!

Upvotes: 0

Views: 1795

Answers (3)

Priyanka
Priyanka

Reputation: 158

  1. Make sure that HasUnevenRows="true" to your listview.HasUnevenRows property will be used to expand the cell height based on the content which is present in the cell.

  2. Apply padding to Grid. EX:<Grid Padding="5">

Upvotes: -1

Andrei
Andrei

Reputation: 115

I have created the needed logic using other Xamarin Forms. This is not to say I have answered the question about ListView and changes will probably need to be done by the Xamarin team, but this is what I came out with to create an expandable List.

XAML

        <ScrollView x:Name="ScrollActivity"  VerticalScrollBarVisibility="Never" >
            <Grid x:Name="GridContent" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20*"/>
                <ColumnDefinition Width="80*"/>

            </Grid.ColumnDefinitions>

            <StackLayout BackgroundColor="#f0dfe2" x:Name="buttonHolder" BindableLayout.ItemsSource="{Binding sideMenu}" >
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <StackLayout BackgroundColor="#f0dfe2">
                                <StackLayout HeightRequest="50" BackgroundColor="#38292c">
                                    <StackLayout.GestureRecognizers>
                                        <TapGestureRecognizer Command="{Binding Source={x:Reference buttonHolder}, Path=BindingContext.ShowHideCommand}"  
                                                              CommandParameter="{Binding .}"/>


                                    </StackLayout.GestureRecognizers>
                                    <Label FontSize="Medium" HorizontalOptions="Center" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"  TextColor="White" Text="{Binding title}"/>
                                </StackLayout>


                                    <StackLayout HeightRequest="{Binding rowHeight}" 

                                                 BindableLayout.ItemsSource="{Binding device}" >
                                        <BindableLayout.ItemTemplate>
                                            <DataTemplate>
                                            <Frame Padding="0" CornerRadius="10">
                                                <Frame.GestureRecognizers>
                                                    <PanGestureRecognizer PanUpdated="PanGestureRecognizer_PanUpdated_1">

                                                    </PanGestureRecognizer>
                                                </Frame.GestureRecognizers>

                                                <Grid HeightRequest="40" BackgroundColor="{Binding btnBkColour}" IsVisible="{Binding visibility}" >

                                                    <Label HorizontalOptions="Center" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" Text="{Binding deviceTitle}" />
                                                </Grid>
                                            </Frame>
                                        </DataTemplate>
                                        </BindableLayout.ItemTemplate>
                                    </StackLayout >

                            </StackLayout>

                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout >




        </Grid>
        </ScrollView>

Command to handle expansion

        public Command ShowHideCommand => new Command(async (sender) =>
        {
            var sideMenu = sender as SideMenuObject;

            if (changeTriggered == false)
            {

                changeTriggered = true;
                if (sideMenu.rowHeight > 0)
                {
                    foreach (SideMenuDevice dev in sideMenu.device)
                    {
                        dev.visibility = false;

                        while (sideMenu.rowHeight >(sideMenu.device.Count - (sideMenu.device.IndexOf(dev) + 1))*40)
                        {
                            sideMenu.rowHeight = sideMenu.rowHeight - 5;
                            await Task.Delay(5);
                        }

                    }

                }
                else
                {
                    foreach (SideMenuDevice dev in sideMenu.device)
                    {
                        while (sideMenu.rowHeight <= (sideMenu.device.IndexOf(dev) +1 ) *40)
                        {
                        sideMenu.rowHeight = sideMenu.rowHeight + 5;
                        await Task.Delay(5);
                        }
                        dev.visibility = true;
                    }
                }
            }

            changeTriggered = false;
        });

Please give feedback, if you can!

Upvotes: 0

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

According to your description, you want to update ListView Row height, I suggest you can binding BoxView height instead of Grid.

From your code, I don't know about DropDownMenu, so I use Button click to change ListView Row, please take a look my code:

<StackLayout>
        <ListView
            HasUnevenRows="False"
            IsGroupingEnabled="true"
            ItemsSource="{Binding groups}"
            SelectionMode="None"
            VerticalScrollBarVisibility="Never">
            <ListView.GroupHeaderTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="5" VerticalOptions="FillAndExpand">
                            <!--<StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding HideShowItems}" CommandParameter="{Binding .}" />
                            </StackLayout.GestureRecognizers>-->
                            <Label
                                HorizontalOptions="Center"
                                HorizontalTextAlignment="Center"
                                Text="{Binding GroupKey}"
                                VerticalOptions="FillAndExpand"
                                VerticalTextAlignment="Center" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <Grid
                                Padding="0"
                                HorizontalOptions="FillAndExpand"
                                VerticalOptions="FillAndExpand">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>
                                <BoxView
                                    BackgroundColor="{Binding BtnColour}"
                                    HeightRequest="{Binding rowHeight}"
                                    HorizontalOptions="FillAndExpand" />
                            </Grid>
                        </ViewCell.View>

                    </ViewCell>

                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button
            x:Name="btn1"
            Clicked="Btn1_Clicked"
            Text="change listview row height" />
    </StackLayout>

 public partial class Page1 : ContentPage
{
    public ObservableCollection<GroupModel> groups { get; set; }

    public Page1()
    {
        InitializeComponent();

        groups = new ObservableCollection<GroupModel>();
        var group1 = new GroupModel() { GroupKey = "Group 1 key" };
        var group2 = new GroupModel() { GroupKey = "Group 2 key" };
        group1.Add(new model1() { rowHeight = 20, BtnColour = Color.Red });
        group1.Add(new model1() { rowHeight = 30, BtnColour = Color.Blue });
        group1.Add(new model1() { rowHeight = 40, BtnColour = Color.Green });

        group2.Add(new model1() { rowHeight = 20, BtnColour = Color.Gray });
        group2.Add(new model1() { rowHeight = 30, BtnColour = Color.Black });
        group2.Add(new model1() { rowHeight = 50, BtnColour = Color.Gold });

        groups.Add(group1);
        groups.Add(group2);
        this.BindingContext = this;


    }

    private void Btn1_Clicked(object sender, EventArgs e)
    {
        groups[0][0].rowHeight = 60;
    }
}


public class GroupModel:ObservableCollection<model1>
{
    public string GroupKey { get; set; }
}
public class model1:ViewModelBase
{
    private double _rowHeight;
    public double rowHeight
    {
        get { return _rowHeight; }
        set
        {
            _rowHeight = value;
            RaisePropertyChanged("rowHeight");
        }
    }


    public Color BtnColour { get; set; }
}

ViewModelBase is the class that implementing INotifyPropertychanged interface.

 public class ViewModelBase : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

          public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

enter image description here

Upvotes: 0

Related Questions