why_vincent why_vincent - 1 month ago 28
C# Question

Xamarin Forms ListView Binding

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); }
}
}

Answer

You need to set your ListViews ItemSource property to a list of items. That list of items should be contained within your ViewModel. Something like this:

<ListView ItemSource="{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 ItemSource like I describe above, with the current ListView XAML you posted and see if that give 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.ItemSource 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.