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.