Michele Rava
Michele Rava

Reputation: 304

In Xamarin.Forms, how to Bind to list of custom class, for ListView and print custom class properties?

In .xaml file I am trying to bind to a listed custom class as ObeservableCollection object. I can successfully update my variables and get the ObservableCollection updated. I can check it rendering it as:

<ListView ItemSource="{Binding myCustomObservableCollection}"/>

However, even if I can determine the number of the entries in the list, I cannot access the properties of my custom class. I tried with this, with no success as list's rows are empty. Even using Text="{Binding Id}" doesn't work since it tells me that "Id" is not a property inside myCustomViewModel:

<ListView
            x:DataType="vm:CustomtViewModel"
            BackgroundColor="LightSlateGray"
            HasUnevenRows="True"
            HorizontalOptions="FillAndExpand"
            ItemsSource="{Binding myCustomObservableCollection}"
            SeparatorColor="Black">
            <ListView.ItemTemplate>
                <DataTemplate>
                   <label Text="{Binding Source={StaticSource myCustomClass}", Path=Id}/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Of course I have inserted my custom class into the .xaml with:

<ContentPage.Resources>
    <local:myCustomClass x:Key="myCustomClass" />
</ContentPage.Resources>

And Id is one of the properties I need into the public class in my Models

namespace myApp.Models {
public class myCustomClass : INotifyPropertyChanged
{
    private string _id;
       public event PropertyChangedEventHandler PropertyChanged;
       public string Id
       {
        get => _id;
        set { 
            _id = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Id)));
            }
        }
    }
}

So I wonder how to effectively read every entry of the list as an object which I could parse the properties in it.

Thanks so much

Upvotes: 0

Views: 688

Answers (2)

Liyun Zhang - MSFT
Liyun Zhang - MSFT

Reputation: 14269

Did you check the official document about Binding Cells in the ListView? The myCustomClass didn't have to inherit from the INotifyPropertyChanged interface.

Just make sure there is public ObservableCollection<myCustomClass> { get; set; } in your viewmodel. Such as:

public class CustomtViewModel
{
     public ObservableCollection<myCustomClass> myCustomObservableCollection { get; set; }
     public CustomtViewModel()
     {
       // you can initialize the myCustomObservableCollection's data in the construction method.
     }
}

In addition, I see you used the x:DataType="vm:CustomtViewModel" for the listview. The official document said:

Set an x:DataType attribute on a VisualElement to the type of the object that the VisualElement and its children will bind to.

So you can just binding the Id like Jason said:

<ListView.ItemTemplate>
     <DataTemplate>
          <Label Text={Binding Id}/>
     </DataTemplate>
</ListView.ItemTemplate>

In addition, you can refer to the official sample about listview mvvm binding on the github.This is the viewmodel's code and the page's code.

Upvotes: 1

Michele Rava
Michele Rava

Reputation: 304

Also thanks to Liyun Zhang and ToolmakerSteve I came up with a solution. Indeed it's important to set the correct x:DataType and I found out it can be done even multiple times pointing at different classes, linking different types of data Here's my ListView in xaml now:

        <ListView
            x:Name="customListName"
            x:DataType="vm:CustomViewModel"
            ItemsSource="{Binding myCustomObservableCollection}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:myCustomClass"> <!--THIS SAVED THE DAY-->
                    <ViewCell>
                        <Label Text="{Binding Id}" /> 
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Now the object extracted from list is correctly read referencing to its own class.

The trick is about adding x:DataType="local:myCustomClass" to the DataTemplate tag after I added a reference in the xaml like this:

<ContentPage.Resources>
    <local:myCustomClass x:Key="myCustomClass" />
</ContentPage.Resources>

(I insert this also here for ease of reading if someone else met the same issue)

It worked like a charm!

Hope this can save someone else from headache! Cheers.

Upvotes: 0

Related Questions