Xamarin.Forms ListView: Infinite loop creating a single viewcell
I have this tiny demo that appears to show that ListView continually creates ViewCells, and binds them to one view model instance, until it runs out of memory. Here's the code...
From MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LVD.MainPage">
<StackLayout>
<Label Text="This is a listview with one item."/>
<Label Text="{Binding MainNum}"/>
<ListView x:Name="DemoList"
ItemsSource="{Binding Itms}"
RowHeight="75"
CachingStrategy="RecycleElement">
</ListView>
</StackLayout>
</ContentPage>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
MainVM _vm = null;
public MainPage()
{
InitializeComponent();
_vm = new MainVM();
BindingContext = _vm;
DemoList.ItemTemplate = new DataTemplate(typeof(myCell));
}
}
MainVM.cs:
using System.Collections.ObjectModel;
namespace LVD
{
class MainVM
{
public string MainNum { get; set; }
private static int _mainserno = 0;
public ObservableCollection<CellVM> Itms { get; set; }
public MainVM()
{
MainNum = "Parent serial#: " + _mainserno.ToString();
_mainserno++;
if (Itms == null)
Itms = new ObservableCollection<CellVM>();
else
Itms.Clear();
CellVM item = new CellVM();
Itms.Add(item);
// If you add a second cell, both sets of numbers count up
//CellVM item2 = new CellVM();
//Itms.Add(item2);
}
}
}
myCell.cs:
using Xamarin.Forms;
namespace LVD
{
class myCell : ViewCell
{
static int _localserialno = 0;
Label VMnumLbl, CellNumLbl, PLbl;
public static readonly BindableProperty ItemProperty =
BindableProperty.Create("CellItem", typeof(CellVM), typeof(myCell), null);
public CellVM CellItem
{
get { return (CellVM)GetValue(ItemProperty); }
set { SetValue(ItemProperty, value); }
}
public myCell()
{
VMnumLbl = new Label();
VMnumLbl.SetBinding(Label.TextProperty, "VMSerNum", BindingMode.Default, null, "VM Serial #: {0}");
CellNumLbl = new Label();
CellNumLbl.SetBinding(Label.TextProperty, "CellSerNum", BindingMode.Default, null, "Cell Serial #: {0}");
// Optional -->
PLbl = new Label();
PLbl.SetBinding(Label.TextProperty, "PingCount", BindingMode.Default, null, "Pings: {0}");
// <--- (and remove the Children.Add below.
var stackit = new StackLayout();
stackit.Children.Add(VMnumLbl);
stackit.Children.Add(CellNumLbl);
stackit.Children.Add(PLbl);
View = stackit;
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
if (BindingContext == null)
CellItem = null;
else if (BindingContext != CellItem)
{
CellItem = (CellVM)BindingContext;
CellItem.CellSerNum = _localserialno++;
// Optional:
CellItem.Ping();
}
}
}
}
CellVM.cs:
class CellVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private static int serialno = 0;
private int _vmserialno;
public int VMSerNum { get { return _vmserialno; } }
public int CellSerNum { get; set; }
public int PingCount { get; set; } // Optional
public CellVM()
{
_vmserialno = serialno++;
PingCount = 0;
}
// Optional:
public void Ping()
{
PingCount++;
OnPropertyChanged(string.Empty);
}
}
When I run this code, the display looks like this:
This is a listview with one item.
Parent serial #: 0
VM Serial #: 0
Cell Serial #: ++
Pings: ++
The bottom two numbers continually increase. That means the listview recreates the CellView, and binds them all to the same viewmodel. If I put two items in the list, both cells have running Cell Serial #'s and Pings.
I posted this on StackOverflow and someone wondered if my PingCount might be causing the problem. It does not. If you remove all references to and uses of PingCount (and both serial numbers, for that matter), and set a breakpoint in the OnBindingContextChanged() method, you'll find that it will continually break there. I added ping count to make this behavior visible. I added the serial numbers to see if it was creating both cells and viewmodels. It only creates the ViewCells, and links them all to the same viewmodel.
Since I couldn't find anyone else complaining about this, I must be doing something wrong. Can anyone enlighten me to what that might be? Obviously, this is a serious showstopper.
advTHANKSance (pun intended)
Developer technologies | .NET | Xamarin
Developer technologies | C#
1 answer
Sort by: Most helpful
-
Deleted
This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.
Comments have been turned off. Learn more