Reputation: 559
I've been fighting with this exception (and subsequent hard crash) for about a day now. I have a ListView in Xamarin Forms that does grouping headers. As much as I can gather from the Call Stack, the error is occurring because of the grouping. I verified this by removing the grouping from the ListView and the app displays the data without crashing. I've even diff'd the code back a few weeks and nothing stands out. This also only occurs on a new launch and subsequent launches don't throw this exception or crash.
How else might I go about further debugging and resolving this?
List View XAML
<ListView x:Name="ListViewItems"
ItemsSource="{Binding ItemsGrouped}"
GroupDisplayBinding="{Binding Key.DisplayText}"
IsGroupingEnabled="true">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<cells:MyGroupHeaderView/>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<cells:ItemCellView />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MyGroupHeaderView XAML
<StackLayout VerticalOptions="Center">
<Label Text="{Binding Key.DisplayText}">
</Label>
</StackLayout>
Grouping C# Code
var result = from s in myItems
orderby s.ItemDateTime
group s by s.GetSortGroupInfo()
into itemGroup
select new Grouping<GroupInfo, ItemViewModel>(itemGroup.Key, itemGroup);
GroupInfo class (used for sorting and display)
public class GroupInfo
{
public string DisplayText { get; set; }
public int SortValue { get; set; }
}
Bound Property and Setter
public ObservableRangeCollection<Grouping<GroupInfo, ItemViewModel>> ItemsGrouped { get; }
= new ObservableRangeCollection<Grouping<GroupInfo, StopViewModel>>();
this.ItemsGrouped.ReplaceRange(
this.MyItems.GroupByDate()
.OrderBy(f => f.Key.SortValue)
.ToList());
Upvotes: 4
Views: 874
Reputation: 559
I found the problem. Turns out when I updated James Montemagno's Xam.Plugin.Geolocator from 3.04 to 4.01, it also switched from PCL to .NET Standard. When I rolled it back, ListView grouping is working again. Unfortunately, I can't get GeoLocation to work with 3.04, and somehow, of all things, I get the above error with 4.01.
Upvotes: 0
Reputation: 4773
The underlying issue is that TemplatedItemsList isn't handling the Reset generated by ReplaceRange well.
As a short-term workaround, you can avoid the crash by not using ReplaceRange:
ItemsGrouped.Clear();
foreach (var item in MyItems.GroupByDate().OrderBy(f => f.Key.SortValue))
{
ItemsGrouped.Add(item);
}
Or set the caching strategy to recycle:
<ListView x:Name="ListViewItems"
ItemsSource="{Binding ItemsGrouped}"
IsGroupingEnabled="true"
CachingStrategy="RecycleElement">
Interestingly if you follow the call chain you come to UnhookItem
which has this comment:
//Hack: the cell could still be visible on iOS because the cells are reloaded after this unhook
//this causes some visual updates caused by a null datacontext and default values like IsVisible
if (Device.RuntimePlatform == Device.iOS && CachingStrategy == ListViewCachingStrategy.RetainElement)
await Task.Delay(100);
item.BindingContext = null;
The crash to me looks to be caused by an attempt to re-render the template because the binding context has changed ... so maybe this hack is also applicable to Android ...
You are setting both the GroupDisplayBinding
and the GroupHeaderTemplate
in the sample code above ... I assume because you were experimenting ... you should only have one set at a time ... using GroupDisplayBinding
would also avoid the issue I expect.
Upvotes: 1