13
votes

Right now I am trying to get a ListView to have some bindable CustomCells. I defined the cells in XAML as a ViewCell under DataTemplate under ListView.ItemTemplate.

Let's just say for simplicity that I have two strings I represent in the Cell. The ViewCell will look something like:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="simpletest.MyPage2">
    <ContentPage.Content>
        <StackLayout Spacing="10" x:Name="layout" Padding="8,10">
            <Label Text="{Binding Something}" />
            <ListView x:Name="listView">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal">
                                <Label Text="{Binding Name}" />
                                <Label Text="{Binding Price}" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

I would really really like to keep this in XAML. I do not like to turn this into a world of bloat by writing the whole thing in C#.

I have a ViewModel for this page and I set the binding context in the code behind file. My question is as follows, do I define a class that extends ViewCell in C# in order to bind the data? As mentioned, I do not want to define layout in C#. I would like to bind in a way like that. I would like to avoid referencing the fields as code behind files tend to reference components. Is this possible? I checked on the Xamarin site and the example uses a mix of code behind and XAML(if I interpret it correctly...).

EDIT 1:

I tried writing a file that mimics some examples, but this is not enough. There is no piece of code explaining that this file is the one that represents the ViewCell in the XAML, and there is no obvious way for me to populate the list without accessing the list-field in codebehind. What am I missing if I just want to add some items to this list using bindings?

public class ReportedAssignmentCell : ViewCell
{
    public ReportedAssignmentCell()
    {
    }

    public static readonly BindableProperty NameProperty = BindableProperty.Create("Name", typeof(string), typeof(ReportedAssignmentCell), "");
    public static readonly BindableProperty PriceProperty = BindableProperty.Create("Price", typeof(string), typeof(ReportedAssignmentCell), "");



    public string Name
    {
        get { return (string)GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }
    public string Price
    {
        get { return (string)GetValue(PriceProperty); }
        set { SetValue(NameProperty, value); }
    }
}
1
The code you have written should be working fine. If you wanted to extend or customize a ViewCell, then you could extend it in C# code and reference it in your XAML, but you do not have to and can do exactly what you are doing above. Are you having a specific problem?hvaughan3
I think I am misunderstanding something fundamental here. I am not sure how to reference the file, you're suggesting that this should be done in the tag? I am also not understanding how I populate the list. I updated my question to make this more obvious.why_vincent
See my answer and let me know if you are still having issueshvaughan3

1 Answers

11
votes

You need to set your ListViews ItemsSource (not ItemSource) property to a list of items. That list of items should be contained within your View. Something like this:

<ListView ItemsSource="{Binding ListOfItems}" ...>
...
</ListView>

Then in your ViewModel:

private ObservableCollection<ItemModel> _listOfItems;
public ObservableCollection <ItemModel> ListOfItems {
    get { return _listOfItems ?? _listOfItems == new ObservableCollection<ItemModel>; }
    set {
        if(_listOfItems != value) {
            _listOfItems = value;
            SetPropertyChanged();
        }
    }

Now, if you wanted to use that custom ReportedAssignmentCell you could, but you could also just leave the StackLayout and Labels in there. Try setting the ItemsSource like I describe above, with the current ListView XAML you posted and see if that gives you the effect you are looking for. If not, let me know.

A ViewCell is meant to hold other items such as StackLayouts and Labels. It but does not have to contain all of the properties that those Labels are going to bind to. The Binding is passed down from the ListView.ItemsSource into your ListView.ItemTemplate. That binding does not need the ViewCell to have any special properties for the binding to work. I hope that makes sense. If not let me know what does not sound right.