Xamarin.Forms: Detect last item in a BindableLayout

Viewed 359

I'm using a bindable layout to display a list of items. The items are bound to an ObservableRangeCollection of key-value pairs

public ObservableRangeCollection<KeyValuePair<string, string>> Items { get; set; }

  

This is the layout that renders the Items -- each one of the rows are separated by a line using BoxView:

<StackLayout BackgroundColor="Transparent" BindableLayout.ItemsSource="{Binding Items}" Padding="20">
    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="1" />
                                </Grid.RowDefinitions>

                                <Label Grid.Column="0"
                                       Grid.Row="0"
                                       Text="{Binding Key}"/>
                                
                                <Label Grid.Column="1"
                                       Grid.Row="0"
                                       HorizontalOptions="End"
                                       HorizontalTextAlignment="End"
                                       Text="{Binding Value}"/>
                                       
                                <BoxView Grid.Column="0"
                                         Grid.Row="1"
                                         Grid.ColumnSpan="2"
                                         HeightRequest="1" />
                            </Grid>
                        </DataTemplate>
   </BindableLayout.ItemTemplate>
 </StackLayout>

The issue is there is an extra line at the end of the list which I wish to hide after rendering the last element in the observable collection.

I would need to figure out if the last item is being rendered on the BindableLayout and set the IsVisible property of the BoxView to false but I'm not sure how to do this using XAML.

2 Answers

One approach is to define a class with a boolean property, that you set on each item to true or false. This controls whether that BoxView appears.

MyItem.cs:

public class MyItem
{
    public string Key { get; set; }
    public string Value { get; set; }
    /// <summary>
    /// Default to "true". Most items will show the line.
    /// </summary>
    public bool ShowLineUnder { get; set; } = true;

MyModelView.cs:

public class MyModelView
{
    public ObservableCollection<MyItem> Items { get; set; }

    public MyModelView()
    {
        Items.Add(new MyItem(...));
        Items.Add(new MyItem(...));
        Items.Add(new MyItem(...));

        // Hide line on last item.
        Items[Items.Count - 1].ShowLineUnder = false;
    }
}

in XAML of ItemTemplate:

<BoxView ... IsVisible="{Binding ShowLineUnder}" />

Adapt as needed.

Another approach would be to consider that each member of the BindingLayout is an entry in the layout's Children collection. With this knowledge, you would only need to hide the BoxView on the last child in the Children collection.

var layout = [reference to the StackLayout];
layout.Children.Last().IsVisible = false; // add using for System.Linq

Besides hiding the BoxView with the IsVisible property, you can also hide it by getting a reference to the grid ColumnDefinition and setting the Width to 0. This can be useful when there is more than one control to hide.

Related