Chris
Chris

Reputation: 1642

Populate a generic List in XAML

I have got a custom Page and a custom Control.

public class TilesPage : ContentPage
{
    public ObservableCollection<Tile> Tiles
    {
        get;
        set;
    }
}

public class Tile : Frame
{
    public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(Tile), null);

    public Tile()
    {
        HasShadow = false;
    }

    public string Title
    {
        get
        {
            return (string)GetValue(TitleProperty);
        }
        set
        {
            SetValue(TitleProperty, value);
        }
    }
}

So my page has a Collection of Tiles, that are Frames. Now I want to populate the Collection via XAML.

My XAML Sytax is like this:

<?xml version="1.0" encoding="utf-8" ?>
<CPages:TilesPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyNamespace.AboutPage"
             xmlns:CControls="clr-namespace:MyNamespace;assembly=MyAssembly"
             xmlns:CPages="clr-namespace:MyNamespace;assembly=MyAssembly"
             >
    <CPages:TilesPage.Tiles>
        <CControls:Tile Title="Test">
            <CControls:Tile.Content>
                <Label>In Tile</Label>
            </CControls:Tile.Content>
        </CControls:Tile>
    </CPages:TilesPage.Tiles>
</CPages:TilesPage>

But the Collection stays empty. The XAML does not touch it.

So what is wrong with my Syntax?

Upvotes: 0

Views: 355

Answers (1)

Sharada
Sharada

Reputation: 13601

There are two issues I see in the code:

  1. We need a default constructor that calls InitializeComponent()

    public TilesPage()
    {
        InitializeComponent();
    }
    
  2. XAML parser expects a not-null collection at this point - so that it can add multiple elements. Else it will throw a parse-exception for either type-mismatch, or null value. To fix that, we need to ensure there is a default value to work with.

    public ObservableCollection<Tile> _tiles = new ObservableCollection<Tile>();
    public ObservableCollection<Tile> Tiles { 
        get { return _tiles; }
        set { _tiles = value; }
    }
    

You should now be able to see the updated collection:

protected override void OnAppearing()
{
    base.OnAppearing();

    Debug.WriteLine(Tiles?.Count);
    foreach (var tile in Tiles)
        Debug.WriteLine(tile.Title);
}

Also, would recommend converting this property to bindable - for easier integration with XAML framework (not mandatory).

public static readonly BindableProperty TilesProperty = 
          BindableProperty.Create(nameof(Tiles), typeof(IList<Tile>), typeof(TilesPage), 
          defaultValue: new ObservableCollection<Tile>());

public IList<Tile> Tiles
{
    get
    {
        return (IList<Tile>)GetValue(TilesProperty);
    }
    set
    {
        SetValue(TilesProperty, value);
    }
} 

Upvotes: 1

Related Questions