How to expand and Collapse ListView in Xamarin Forms

10,163

Solution 1

In ListView to show the data just take one GridLayout in ViewCell. Take two rows with height auto in GridLayout. In first row show header and button and in second row just add that item relatesd data and bind one isvisible property to that second row. On click of that up arrow just inverse the value of isvisible property.

That is if the property of isvisible is true then it will show the 2 row and if isvisible property is false then will just show you that header.

<ListView.ItemTemplate>
  <DataTemplate>
            <ViewCell>
      <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />           
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="40"/>
        </Grid.ColumnDefinitions>
                <Label Text="{Binding HeaderText}" Grid.Row="0" 
                       Grid.Column="0" />
                <Button Text="Show"  Grid.Row="0" Grid.Column="1" 
                        Clicked="LableVisibleButton"/>
                <Label
                   Grid.Row="1" Grid.Grid.ColumnSpan="2"
                   FormattedText="{Binding FormattedText}" IsVisible="
                   {Binding LabelVisible}"/>
            </ViewCell>

Solution 2

I've done it in notepad so haven't tested it. Moreover I generally don't do xaml. However, this should work. I just added 2 buttons on top of your grid, bound to the same command that toggles a boolean to say wether your grid should be visible or not.

Your ViewModel:

namespace XamlSamples.Models
{
    public class Phone
    {
        public string mobile { get; set; }
        public string home { get; set; }
        public string office { get; set; }
    }

    public class Contact
    {
        public string id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
        public string address { get; set; }
        public string gender { get; set; }
        public Phone phone { get; set; }
        public bool IsCollapsed { get; private set; }
        public ICommand ToggleCollapseCommand { get; }

        public Contact() => ToggleCollapseCommand = new Command(_ => IsCollapsed = !IsCollapsed);
    }

    public class ContactList
    {
        public List<Contact> contacts { get; set; }
    }

    public class InvertBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => !(bool)value;

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => !(bool)value;
    }
}

Your view:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:models="clr-namespace:XamlSamples.Models;assembly=XamlSamples"
         x:Class="XamlSamples.CollapsableListView">
<ContentPage.Resources>
    <ResourceDictionary>
        <models:InvertBoolConverter x:Key="invertBoolConverter" />
    </ResourceDictionary>
</ContentPage.Resources>
<Grid>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Margin="10" Text="Display Json Data" FontSize="25" />
        <ListView x:Name="listviewConacts" Grid.Row="1" HorizontalOptions="FillAndExpand" HasUnevenRows="True" ItemSelected="listviewContacts_ItemSelected">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Vertical">
                            <Button Text="Tap to Uncollapse" Command="{Binding ToggleCollapseCommand}" IsVisible="{Binding IsCollapsed}"/>
                            <Button Text="Tap to Collapse" Command="{Binding ToggleCollapseCommand}" IsVisible="{Binding IsCollapsed, Converter={StaticResource invertBoolConverter}}"/>
                            <Grid HorizontalOptions="FillAndExpand" Padding="10" IsVisible="{Binding IsCollapsed, Converter={StaticResource invertBoolConverter}}">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <Label Text="{Binding name}" HorizontalOptions="StartAndExpand" Grid.Row="0" TextColor="Blue"  FontAttributes="Bold"/>
                                <Label Text="{Binding email}" HorizontalOptions="StartAndExpand" Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                <Label Text="{Binding phone.mobile}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" Grid.Row="3" HorizontalOptions="FillAndExpand" />
                            </Grid>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    <ActivityIndicator x:Name="ProgressLoader" IsRunning="True"/>
</Grid>
Share:
10,163
MilkBottle
Author by

MilkBottle

Love everything under the hot sun

Updated on June 22, 2022

Comments

  • MilkBottle
    MilkBottle about 2 years

    I'm new to Xamarin Forms and I understand that there are many useful controls. I'm looking for a control that can expand to show data in a grid like in the example below.

    expand and collapse example

    Update

    Model:

    public class Phone
    {
        public string mobile { get; set; }
        public string home { get; set; }
        public string office { get; set; }
    }
    
    public class Contact
    {
        public string id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
        public string address { get; set; }
        public string gender { get; set; }
        public Phone phone { get; set; }
    }
    
    public class ContactList
    {
        public List<Contact> contacts { get; set; }
    }
    

    XAML:

    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Label Grid.Row="0" Margin="10" Text="Display Json Data" FontSize="25" />
            <ListView x:Name="listviewConacts" Grid.Row="1" HorizontalOptions="FillAndExpand" HasUnevenRows="True" ItemSelected="listviewContacts_ItemSelected">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Grid HorizontalOptions="FillAndExpand" Padding="10">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <Label Text="{Binding name}" HorizontalOptions="StartAndExpand" Grid.Row="0" TextColor="Blue"  FontAttributes="Bold"/>
                                <Label Text="{Binding email}" HorizontalOptions="StartAndExpand" Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                <Label Text="{Binding phone.mobile}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" Grid.Row="3" HorizontalOptions="FillAndExpand" />
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
        <ActivityIndicator x:Name="ProgressLoader" IsRunning="True"/>
    </Grid>
    

    Based on the model and XAML above, how can I achieve an expandable and collapsible ListView such as the one in image above?