I'm binding a customer list to a Xamarin Listview. I want to use a DataTemplate with a ViewCell in it.
As per documentation, we can use one of 2 constructors:
new DataTemplate(typeof(CustomerViewCell));
new DataTemplate(=>new CustomerViewCell);
However, they lead to different results. The first one correctly displays the list, while the second one shows repeated the last item of the list.
Do I don't know something basic here?
Here's my customer model:
public class Customers : List<Customer>
{
public Customers()
{
Add(new Customer { No = 1, Name = "Microsoft" });
Add(new Customer { No = 2, Name = "Google" });
Add(new Customer { No = 3, Name = "Facebook" });
}
}
public class Customer {
public int No { get; set; }
public string Name { get; set; }
}
And here is the CustomerViewCell.xaml, which is inherited from ViewCell
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="LVDataTemplate.View.CustomerViewCell">
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding No}" />
<Label Text="{Binding Name}" />
</StackLayout>
</ViewCell.View>
</ViewCell>
The CustomerListView, which shows the Customers:
public partial class CustomerListView :ContentPage
{
public CustomerListView()
{
InitializeComponent();
MyListView.ItemsSource = new Customers();
//1. Work correctly
// MyListView.ItemTemplate = new DataTemplate(typeof(CustomerViewCell));
//2. Work in-correctly. only the last item repeated through out the list
var theCell = new CustomerViewCell();
MyListView.ItemTemplate = new DataTemplate(()=>theCell);
}
}
The first code shows the result:
The second shows
Please read the document here: data-templates/creating
The method public DataTemplate(Func<object> loadTemplate);
is use to create a datatemplate as a resource, so the correct usage of the second constructor is:
var personDataTemplate = new DataTemplate(() => {
return new ViewCell1();
});
Resources = new ResourceDictionary();
Resources.Add("personTemplate", personDataTemplate);
testListView.ItemTemplate = (DataTemplate)Resources["personTemplate"];
Or you can customize the ViewCell like this:
var personDataTemplate = new DataTemplate (() => {
var grid = new Grid ();
...
return new ViewCell { View = grid };
});
Also, you can use personDataTemplate directly without define it as a resource:
testListView.ItemTemplate = personDataTemplate;
The problem of your code is you should create theCell inside the block, you can use:
var personDataTemplate = new DataTemplate(() => {
return new ViewCell1();
});
Or
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
testListView.ItemTemplate = new DataTemplate(() => test());
}
public ViewCell1 test() {
//other actions
return new ViewCell1();
}
}
The first constructor MyListView.ItemTemplate = new DataTemplate(typeof(CustomerViewCell));
is creating-a-datatemplate-with-a-type, that is correct.