Xamarin Forms displaying simple lists

I have a list of an object and I just want to display a couple of labels for each item.

In the asp.net days I would use a repeater with the labels inside.

I realized there is no repeater in Xamarin Forms, or is there?

I tried using a Listview but it doesn't work because in IOS it creates empty rows till the end of the screen.

Is there an alternative to ListView?

This would be the idea:

<repeater:RepeaterView 
          ItemsSource="{Binding MyObject}">

              <Label Text="{Binding Prop1 }"/>
               <Label Text="{Binding Prop2 }"/>

 </repeater:RepeaterView>

How to implement this in Xamarin Forms?

Is there a native way to achieve this or only using 3rd party libraries?

Thanks

Upvotes: 2

Views: 1461

Answers (4)

opewix
opewix

Reputation: 5083

BindableLayout is already mentioned but I'd like to highlight it in a separate answer. No need to use custom "repeaters" anymore.

<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
             Orientation="Horizontal"
             ...>
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <controls:CircleImage Source="{Binding}"
                                  Aspect="AspectFill"
                                  WidthRequest="44"
                                  HeightRequest="44"
                                  ... />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

Upvotes: 1

Almir Vuk
Almir Vuk

Reputation: 3173

You can accomplish that using custom control called RepeaterView, there are couple of similar implementations out-there, however Xamarin MVP Houssem Dellai made nice example how to use RepeaterView, with also example of how to include Tapped event with it.

Here is XAML usage snippet:

 <repeater:RepeaterView ItemsSource="{Binding YourCollection}">

            <repeater:RepeaterView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="20"
                              Margin="10">

                            <Grid.GestureRecognizers>
                                <TapGestureRecognizer Tapped="Student_Tapped" />
                            </Grid.GestureRecognizers>

                            <Label Text="{Binding SomePropertyOfYourModel}"
                                   FontSize="36" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </repeater:RepeaterView.ItemTemplate>
        </repeater:RepeaterView>

You can find full example on his GitHub page: https://github.com/HoussemDellai/Xamarin-Forms-RepeaterView

Nuget that he use: https://www.nuget.org/packages/XamarinForms.Plugin.Repeater/

And there is also Youtube video where he explains it: https://www.youtube.com/watch?v=UhoJktzceak

31.12.2019 EDIT:

Xamarin.Forms now support Bindable Layouts, so you can take a look at the official support for this kind of behaviour.

https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/bindable-layouts

Upvotes: 4

DavidS
DavidS

Reputation: 2934

I tried using a Listview but it doesn't work because in IOS it creates empty rows till the end of the screen.

If this is the only reason you aren't using ListView, there is a simple solution: insert an empty footer on the Forms side. While Cole Xia had the right idea, you can do it without a custom renderer:

<ListView ...>
  <ListView.Footer>
    <StackLayout></StackLayout>
  </ListView.Footer>

If the Footer is null, you get the empty rows that you observe. So there needs to be non-null footer, and an empty StackLayout does the trick to avoid empty rows.

Upvotes: 0

ColeX
ColeX

Reputation: 14475

I tried using a Listview but it doesn't work because in IOS it creates empty rows till the end of the screen.

As Vahid said, we can create custom renderer to fix this issue.

[assembly: ExportRenderer(typeof(ListView), typeof(CustomListViewRenderer))]
namespace twoWayBinding.iOS
{
    class CustomListViewRenderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
                return;

            var tableView = Control as UITableView;
            tableView.TableFooterView = new UIView(frame: CGRect.Empty);
        }
    }
}

Refer to How to remove empty cells in UITableView?

Upvotes: 0

Related Questions