0
votes

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:

  1. new DataTemplate(typeof(CustomerViewCell));

  2. 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:

  1. Microsoft.
  2. Google
  3. Facebook

The second shows

  1. Facebook
  2. Facebook
  3. Facebook
1
what specific docs are you reading that show the 2nd format?Jason

1 Answers

0
votes

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.