简体   繁体   中英

How to create a simple Xamarin.Forms Items View

If you're a Xamarin.Forms developer, you've most likely had issues with the built in ListView . Wouldn't it be easier with a simple repeater to bind an ItemsSource using a DataTemplate ? That's what I thought.

In SL / WPF there is an ItemsControl that works just like that - no design, no selection, just repeating items.

Now there is one in XLabs, but if you don't want all of them packages, here is a simpler solution, based on this article by QiMata.

Tools:

  • Visual Studio 2015 @ Win 10 (or use Xamarin Studio / on OS X)
  • Xamarin 4 stable (VS plugin)
  • Xamarin.Forms 2.1.0.6529

Create a new class in your Xamarin.Forms PCL project. I named mine HliItemsView (since "View" is the term for "Controls" in XF and Hli is my brand).

Paste this code and modify as needed.

I based my view on a ScrollView since it's a list. This way the items will automatically scroll just like ListView .

using System;
using System.Collections;

using Xamarin.Forms;

namespace HLI.Forms.Controls
{
    public class HliItemsView : ScrollView
    {
        public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
            "ItemTemplate",
            typeof(DataTemplate),
            typeof(HliItemsView),
            null,
            propertyChanged: (bindable, value, newValue) => Populate(bindable));

        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
            "ItemsSource",
            typeof(IEnumerable),
            typeof(HliItemsView),
            null,
            BindingMode.OneWay,
            propertyChanged: (bindable, value, newValue) => Populate(bindable));

        public IEnumerable ItemsSource
        {
            get
            {
                return (IEnumerable)this.GetValue(ItemsSourceProperty);
            }

            set
            {
                this.SetValue(ItemsSourceProperty, value);
            }
        }

        public DataTemplate ItemTemplate
        {
            get
            {
                return (DataTemplate)this.GetValue(ItemTemplateProperty);
            }

            set
            {
                this.SetValue(ItemTemplateProperty, value);
            }
        }

        private static void Populate(BindableObject bindable)
        {
            var repeater = (HliItemsView)bindable;

            // Clean
            repeater.Content = null;

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

            // Create a stack to populate with items
            var list = new StackLayout();

            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;

                list.Children.Add(view);
            }

            // Set stack as conent to this ScrollView
            repeater.Content = list;
        }
    }
}

There are a several differences between the Xaml from WPF and Xamarin, which you see here .

However there is a ItemsControl sample implementation (source code), fully functional, from the Xamarin GitHub repo, which you can find here .

Sample usage can be found below:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
...
             xmlns:local="clr-namespace:YourNameSpaceHere" 
...
      

Then you instantiate the ItemsControls like this:

        <local:ItemsControl x:Name="CardsPicked" ItemsSource="{Binding Path=Deck.CardsPicked, Mode=TwoWay}" Grid.Row="3" Orientation="Horizontal" HorizontalOptions="Center" >
            <local:ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Image Source="{Binding CardType, Converter={StaticResource CardTypeImageConverter}}" MinimumHeightRequest="140" Aspect="AspectFit" Margin="4"></Image>
                </DataTemplate>
            </local:ItemsControl.ItemTemplate>
        </local:ItemsControl>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM