Home > Enterprise >  In Xamarin.Forms, how to Bind to list of custom class, for ListView and print custom class propertie
In Xamarin.Forms, how to Bind to list of custom class, for ListView and print custom class propertie

Time:12-15

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

CodePudding user response:

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 adddition, 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.

CodePudding user response:

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.

  • Related