Xamarin Forms Repeater View

microsoft xamarin heros c# iOS Android UWP

A ListView is a kind of repeater but isn’t always what I want. It’s surprising something like this isn’t included in the framework but making your own is fairly simple.

namespace PSC.Controls
{
    /// <summary>
    /// Repeater view.
    /// </summary>
    public class RepeaterView : StackLayout
    {
        /// <summary>
        /// The item template property.
        /// </summary>
        public static readonly BindableProperty ItemTemplateProperty = 
                BindableProperty.Create(
                    "ItemTemplate",
                    typeof(DataTemplate),
                    typeof(RepeaterView),
                    null,
                    propertyChanged: (bindable, value, newValue) => 
                        Populate(bindable));

        /// <summary>
        /// The items source property.
        /// </summary>
        public static readonly BindableProperty ItemsSourceProperty = 
            BindableProperty.Create(
                "ItemsSource",
                typeof(IEnumerable),
                typeof(RepeaterView),
                null,
                BindingMode.OneWay,
                propertyChanged: (bindable, value, newValue) => 
                  Populate(bindable));

        /// <summary>
        /// Gets or sets the items source.
        /// </summary>
        /// <value>The items source.</value>
        public IEnumerable ItemsSource
        {
            get => (IEnumerable)this.GetValue(ItemsSourceProperty);
            set => this.SetValue(ItemsSourceProperty, value);
        }

        /// <summary>
        /// Gets or sets the item template.
        /// </summary>
        /// <value>The item template.</value>
        public DataTemplate ItemTemplate
        {
            get => (DataTemplate)this.GetValue(ItemTemplateProperty);
            set => this.SetValue(ItemTemplateProperty, value);
        }

        /// <summary>
        /// Populate the specified bindable.
        /// </summary>
        /// <returns>The populate.</returns>
        /// <param name="bindable">Bindable.</param>
        private static void Populate(BindableObject bindable)
        {
            var repeater = (RepeaterView)bindable;

            // Clean
            repeater.Children.Clear();

            // Only populate once both properties are received
            if (repeater.ItemsSource == null || 
                repeater.ItemTemplate == null)
                return;

            foreach (var viewModel in repeater.ItemsSource)
            {
                var content = repeater.ItemTemplate.CreateContent();
                if (!(content is View) && !(content is ViewCell))
                {
                    throw new Exception(
                          $"Invalid visual object {nameof(content)}");
                }

                var view = content is View ? content as View : 
                                             ((ViewCell)content).View;
                view.BindingContext = viewModel;

                repeater.Children.Add(view);
            }
        }
    }
}



The view is based on StackLayout which will take care of positioning the items.

There are a couple of bindable properties – ItemTemplate for the item layout and ItemsSource which provides the items. Note that ItemsSource hooks an action to PropertyChanging – I’ll come back to this later on.

Usage in XAML is similar to ListView, with an ItemTemplate, DataTemplate, and ViewCell.

<ui:Repeater x:Name="MainRepeater">
    <ui:Repeater.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Label Text="{Binding Title}" 
                           HorizontalOptions="StartAndExpand" 
                           VerticalTextAlignment="Center"/>
                    <Button Text="Select" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ui:Repeater.ItemTemplate>
</ui:Repeater>

Don’t forget to define ui

<ContentPage xmlns="https://xamarin.com/schemas/2014/forms" 
    xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:ui="clr-namespace:PSC.Controls;assembly=PSC.Controls">

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.