To create a list page, use the CollectionView component. It's a highly efficient view that works by recycling views, similar to the Android Collection View.
<z-Component z-type="ShoeItem" z-base="Row" z-viewmodel="ViewModel.ShoesPage.Item" on-Tapped="@{Model.Tap()}">
<ImageView Path="@{Model.ImageUrl}" />
<TextView Text="@{Model.Brand}"/>
</z-Component>
</CollectionView>
The View model for the above example is:
{
public readonly CollectionViewModel<Item> Items = new CollectionViewModel<Item>();
protected override void NavigationStarted()
{
var shoes = Enumerable.Range(1, 100).Select(v => new Domain.Shoe { Brand = "Shoe " + v }).ToArray();
Items.Replace(shoes); // Note: Instances of the Item class will be automatically created and binded from the domain source.
}
public class Item : ViewModel<Domain.Shoe>
{
public Bindable<string> ImageUrl => Source.Get(x => x.ImageUrl);
public Bindable<string> Brand => Source.Get(x => x.Brand);
public void Tap()
{
The<ShoePage>().Source.Set(Source);
Forward<ShoePage>();
}
}
}
You can use a CollectionView to render your items horizontally by specifying Direction="Horizontal".
Important note: When using the horizontal mode, your item template definition must provide a pre-determined width. By default in Zebble, the width size is set as automatic by container which will not work for a horizontal list as it creates an infinite loop (the list total width depends on its children, and the child width depends on its parent list!). Therefore to avoid problems, make sure to set a pre-determined width for the item template.
The easiest way is to set a fixed width for it such as "50px". For example:
<z-Component z-type="ShoeItem" z-base="Row" z-viewmodel="ViewModel.ShoesPage.Item" on-Tapped="@{Model.Tap()}" Width="50px">
<ImageView Path="@{Model.ImageUrl}" />
<TextView Text="@{Model.Brand}"/>
</z-Component>
</CollectionView>
Alternatively you can make this automatic by content. But if you do so, you need to make sure that none of its children have their width set as the default which is automatic by container. If you need automatic sizing for the list items, every child in the list item hierarchy should either have its width set as a fixed value, or by content.
<z-Component z-type="ShoeItem" z-base="Row" z-viewmodel="ViewModel.ShoesPage.Item" on-Tapped="@{Model.Tap()}" Width="Content">
<ImageView Path="@{Model.ImageUrl}" Width="20px" />
<TextView Text="@{Model.Brand}" Width="Content"/>
</z-Component>
</CollectionView>