xamarin.android - Xamarin.Forms ListView with uneven row hight not updating layout if items change size after an item has been deleted -
i developing app uses list view show list of appointments. selected appointment , meet conditions should expanded , show information , others should show summarised version. have implemented using listview
it's itemtemplate
set datatemplate
containing stacklayout
contains various elements. of these elements have isvisible
property bound bool property on view model updated depending on whether item should expanded. listview
has it's hashunevenrows
set true , rowheight
set -1.
when item deleted items collection correctly removed after point other item below on screen (except last item seem work) not change in size though "expand" property being changed , items appear overlayed on other elements there. if items scrolled off screen start working again.
i have developed small test app shows same behaviour simpler , performs actions in response gui interaction remove possibility of being multi threading issues. simple app has button remove top item , list view containing numbered items if not selected number , if selected show "expanded" above number. after items have been deleted size of rows no longer update , stays @ height had when item deleted. causing selected row have white space above number , new rows either show "expanded" or show overlayed on number.
full source code available @ https://github.com/staircase27/xamarinformsandroidlistviewerror/tree/master
the main pages .xaml file contains
<contentpage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="listviewerror.mainpage" x:name="page" bindingcontext="{x:reference page}"> <stacklayout orientation="vertical"> <button clicked="menuitem_onclicked" text="remove first item" /> <listview itemssource="{binding items}" itemselected="listview_onitemselected" hasunevenrows="true" rowheight="-1"> <listview.itemtemplate> <datatemplate> <viewcell> <stacklayout orientation="vertical"> <label isvisible="{binding expand}" text="expanded" verticaltextalignment="center" horizontaltextalignment="center" /> <label text="{binding id}" verticaltextalignment="center" horizontaltextalignment="center" /> </stacklayout> </viewcell> </datatemplate> </listview.itemtemplate> </listview> </stacklayout> </contentpage>
and relevant parts of code behind file are
public partial class mainpage { public mainpage() { _items = new observablecollection<item>(enumerable.range(0, 10).select(i => new item(i))); initializecomponent(); } public ienumerable<item> items => _items; public sealed class item : inotifypropertychanged { public item(int id) { id = id; expand = false; } public int id { get; } public bool expand { { return _expand; } set { if (value == _expand) return; _expand = value; onpropertychanged(); } } public event propertychangedeventhandler propertychanged; [notifypropertychangedinvocator] private void onpropertychanged([callermembername] string propertyname = null) { propertychanged?.invoke(this, new propertychangedeventargs(propertyname)); } private bool _expand; } private void listview_onitemselected(object sender, selecteditemchangedeventargs e) { if (_selecteditem != null) _selecteditem.expand = false; _selecteditem = e.selecteditem item; if (_selecteditem != null) _selecteditem.expand = true; } private void menuitem_onclicked(object sender, eventargs e) => _items.removeat(0); private item _selecteditem; private readonly observablecollection<item> _items; }
this code has been tested using xamarin 4.4.0.34 , xamarin.forms nuget package 2.3.4.224 same behaviour seen older versions too. both developed using visual studio 2015.
in demo app have tried workaround think of reset itemssource
on listview
fix issue loses current selection. have worked around issues resetting the selecteditem
cause selected item picked again. neither of these option main app though changes collection come multiple places , collection provided external component watching changes not easy. list in main app relatively large , there many components in gui per item reloaded entire list change collection expensive , make app hard use. workaround included in respository linked above , requires changing menuitem_onclicked
function to
_items.removeat(0); item selecteditem = _selecteditem; listview.selecteditem = null; listview.itemssource = null; listview.itemssource = items; listview.selecteditem = selecteditem;
screenshots
app working: app broken (see entries 7 (not expanded) , 8 (expanded when shouldn't be)):
note: code , issue has not been tested on ios or uwp not have access these platforms test on.
Comments
Post a Comment