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 which are not used. Just empty rows, this is forcing my button to display at the bottom of the 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>
Picture of the list and button:
An easy way to remove the empty rows of a ListView is to set an empty footer for the ListView.
ListView HeaderList = new ListView()
{
Footer = ""
};
or in XAML
<ListView x:Name="HeaderList" Footer=""></ListView>
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));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With