Jazz W Jazz W - 1 month ago 15
C# Question

How to hide the empty rows of a list view in xamarin.forms

I have a StackLayout with a ListView and i have an add-button that i want to display right under the ListView. But the ListView displays many rows witch are not used. Just empty rows, this is forcing my button to display at the lower page. I've been messing with the VerticalOptions all day but cannot get the rows to disappear.

This is my XAML code :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:LiquitMobileApp"
x:Class="LiquitMobileApp.MainPage"
Title="Settings"
>

<StackLayout BackgroundColor="LightGray">
<Label Text="Liquit Zones" TextColor="Gray" FontSize="Small" Margin="10"/>
<StackLayout AbsoluteLayout.LayoutBounds="10,10,10,10">
<ListView x:Name="UsingZone" SeparatorColor="LightGray" ItemTapped="ZonesList_ItemTapped" RowHeight="60" BackgroundColor="Green" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnEdit" Text="Edit" />
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}" Text="Trash" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15, 5, 0, 0" Orientation="Horizontal" BackgroundColor="White">
<Image Source="{Binding Image}" HorizontalOptions="Start" AbsoluteLayout.LayoutBounds="250.25, 0.25, 50, 50 "/>
<StackLayout Orientation="Vertical">
<Label Text = "{Binding Name}" FontSize="20" TextColor="Black" AbsoluteLayout.LayoutBounds="0.25, 0.25, 400, 40"/>
<Label Text = "{Binding Address}" TextColor="LightGray" AbsoluteLayout.LayoutBounds="50, 35, 200, 25"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Label />
</ListView.Footer>
</ListView>
<Button Text="Add Zone" TextColor="Black" HorizontalOptions="FillAndExpand" FontSize="Medium" Clicked="Button_Clicked" BackgroundColor="White"/>
</StackLayout>
</StackLayout>
</ContentPage>


Click this link for the picture of the list and the add-button

Answer Source

So, the solution I found is to force listview layout every time you add/remove an item. You also need to wrap the list in stacklayout.

<StackLayout BackgroundColor="LightGray">
    <Label Text="Liquit Zones" TextColor="Gray" FontSize="Small" Margin="10"/>

    <StackLayout>
    <ListView x:Name="ItemsListView" SeparatorColor="LightGray" BackgroundColor="Green" RowHeight="60" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <ViewCell.ContextActions>
                        <MenuItem Clicked="AddItemClicked" Text="Add" />
                        <MenuItem Clicked="RemoveItemClicked" CommandParameter="{Binding .}" Text="Trash" IsDestructive="True" />
                    </ViewCell.ContextActions>
                    <StackLayout Padding="15, 5, 0, 0" Orientation="Horizontal" BackgroundColor="White">
                        <Image Source="{Binding Image}" HorizontalOptions="Start"/>
                        <StackLayout Orientation="Vertical">
                            <Label Text = "{Binding ItemText}" FontSize="20" TextColor="Black" />
                            <Label Text = "{Binding ItemDetail}" TextColor="LightGray" />
                        </StackLayout>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.Footer>
            <Label />
        </ListView.Footer>
    </ListView>
    </StackLayout>

    <Button Text="Add Item" TextColor="Black" HorizontalOptions="FillAndExpand" FontSize="Medium" Clicked="AddItemClicked" BackgroundColor="White"/>
</StackLayout>

Because you know your cell height you can do this:

       void AddItemClicked(object sender, EventArgs e)
        {
            SampleData data = new SampleData();
            data.ItemText = "An Item";
            data.ItemDetail = "Item - " + (itemsListCollection.Count + 1).ToString();
            itemsListCollection.Add(data);

            ItemsListView.HeightRequest = itemsListCollection.Count * 60;
            //ForceLayout();
        }

    void RemoveItemClicked(object sender, EventArgs e)
    {

        SampleData item =(SampleData)((MenuItem)sender).CommandParameter;
        if (item != null)
        {
            itemsListCollection.Remove(item);
        }
        ItemsListView.HeightRequest = itemsListCollection.Count * 60;

    }


class SampleData:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string itemText;
    public string ItemText
    {
        get
        {
            return itemText;
        }
        set
        {
            itemText = value;
            NotifyPropertyChanged("ItemText");
        }
    }
    private string itemDetail;
    public string ItemDetail
    {
        get
        {
            return itemDetail;
        }
        set
        {
            itemDetail = value;
            NotifyPropertyChanged("ItemDetail");
        }
    }
    private void NotifyPropertyChanged(string propName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}

enter image description here