Open Magendanz opened 6 years ago
@Magendanz Please try and use RecycleElementAndDataTemplate
. If the issue still reproduces, please see if @hartez reproduction demonstrates your issue (it works for me).
With this set, I now get an exception: System.NotSupportedException: RecycleElementAndDataTemplate requires DataTemplate activated with ctor taking a type.
@Magendanz That's expected if the DataTemplate is not constructed using the override that takes a type. Can you can return a DataTemplate from the Selector that takes a Type during construction? That is most efficient -- otherwise try simply RecycleElement.
@ez On master I'm unable to reproduce the issue with the attached reproduction. It could be that it's been fixed or possibly only reproduces on a specific environment. I'm running 11.2 as well.
Okay, using the DataTemplate constructor that takes a type works around the problem. (For those looking for sample code, I finally found it here.) The default CachingStrategy and CachingStrategy.RecycleElement weren't working on iOS for me, though.
@Magendanz That's expected if the DataTemplate is not constructed using the override that takes a type. Can you can return a DataTemplate from the Selector that takes a Type during construction? That is most efficient -- otherwise try simply RecycleElement.
@ez On master I'm unable to reproduce the issue with the attached reproduction. It could be that it's been fixed or possibly only reproduces on a specific environment. I'm running 11.2 as well.
Using the type constructor still isn't working for me. CanRecycle of the DataTemplate is false, despite setting the RecycleElementAndDataTemplate attribute.
Update: I was still incorrectly instantiating the templates left in my Xaml. They have to be constructed by the constructor.
Yeah, this is what worked for me:
public class ListTemplateSelector : DataTemplateSelector
{
private readonly DataTemplate householdTemplate = new DataTemplate(typeof(HouseholdCell));
private readonly DataTemplate childTemplate = new DataTemplate(typeof(ChildCell));
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
=> item is HouseholdViewModel ? householdTemplate : childTemplate;
}
I am finding RecycleElementAndDataTemplate to effect scrolling performance quite significantly, where as RetainElmenet does not. I haven't noticed issues with RetainElement when adding more than 20 items of the same template. Should I continue to use RetainElement or will I run into problems with the note here?: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector
"On Android, there can be no more than 20 different data templates per ListView."
@UnreachableCode I believe that's referring to the number of different templates, not the number of items which use that template. So you shouldn't run into any issues.
@Magendanz That's expected if the DataTemplate is not constructed using the override that takes a type. Can you can return a DataTemplate from the Selector that takes a Type during construction? That is most efficient -- otherwise try simply RecycleElement.
@kingces95 what if the viewcell is defined in the Resources of the page itself, as in my case:
<pages:BaseContentPage.Resources>
<DataTemplate x:Key="IncomingTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="OutGoingTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<viewcells:ChatTemplateSelector
x:Key="ChatTemplateSelector"
IncomingTemplate="{StaticResource IncomingTemplate}"
OutgoingTemplate="{StaticResource OutGoingTemplate}" />
</pages:BaseContentPage.Resources>
...
<customviews:EnhancedListView
ItemTemplate="{StaticResource ChatTemplateSelector}"
<x:Arguments>
<ListViewCachingStrategy>RecycleElementAndDataTemplate</ListViewCachingStrategy>
</x:Arguments>
</customviews:EnhancedListView>
Im getting the same error as @Magendanz 'RecycleElementAndDataTemplate requires DataTemplate activated with ctor taking a type.'
My ChatTemplateSelector looks like this:
public class ChatTemplateSelector : DataTemplateSelector
{
public DataTemplate IncomingTemplate { get; set; }
public DataTemplate OutgoingTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is Message messageVm)
{
return messageVm.IsIncoming ? IncomingTemplate : OutgoingTemplate;
}
return null;
}
}
@Magendanz That's expected if the DataTemplate is not constructed using the override that takes a type. Can you can return a DataTemplate from the Selector that takes a Type during construction? That is most efficient -- otherwise try simply RecycleElement.
@kingces95 what if the viewcell is defined in the Resources of the page itself, as in my case:
<pages:BaseContentPage.Resources> <DataTemplate x:Key="IncomingTemplate"> <ViewCell> ... </ViewCell> </DataTemplate> <DataTemplate x:Key="OutGoingTemplate"> <ViewCell> ... </ViewCell> </DataTemplate> <viewcells:ChatTemplateSelector x:Key="ChatTemplateSelector" IncomingTemplate="{StaticResource IncomingTemplate}" OutgoingTemplate="{StaticResource OutGoingTemplate}" /> </pages:BaseContentPage.Resources> ... <customviews:EnhancedListView ItemTemplate="{StaticResource ChatTemplateSelector}" <x:Arguments> <ListViewCachingStrategy>RecycleElementAndDataTemplate</ListViewCachingStrategy> </x:Arguments> </customviews:EnhancedListView>
Im getting the same error as @Magendanz
'RecycleElementAndDataTemplate requires DataTemplate activated with ctor taking a type.'
My ChatTemplateSelector looks like this:
public class ChatTemplateSelector : DataTemplateSelector { public DataTemplate IncomingTemplate { get; set; } public DataTemplate OutgoingTemplate { get; set; } protected override DataTemplate OnSelectTemplate(object item, BindableObject container) { if (item is Message messageVm) { return messageVm.IsIncoming ? IncomingTemplate : OutgoingTemplate; } return null; } }
I have the same question. Can anyone clarify? Thanks in advance :)
Any update on this ticket? In our case, we have filtering we apply and then update the data source depending on the selected filter. As soon as the user switch from the 'All' list to 'selected option', the ListView starts showing blank cells. Sometimes it shows like a last line of the text in the cell. However, if we try to do any interaction on that cell maybe touch or so, the data starts showing up. Again, if we scroll up and down, the issue comes back. Once this behavior starts, it is very difficult to avoid it. We have to close the page and re-open.
Any update on this would be really great!
When using a ListView with a DataTemplateSelector, cells scrolled into view appear either partially or fully blank. The bound collections are still there, since clicking the blank cells brings up the correct detail page, but it seems the cached views have been disposed.
Bypassing the DataTemplateSelector and setting the ItemTemplate to a single DataTemplate fixes the problem (but you're stuck with the single DataTemplate). Also, you won't see the issue as long as you're viewing cells that are all resolved to the same DataTemplate. It's only when you start switching between templates that the cell contents start disappearing when scrolled into view.
Note: This problem only occurs on iOS platform. Everything works as expected on Android.
Steps to Reproduce
Expected Behavior
New cells should scroll into view
Actual Behavior
Cells scrolling into view are either completely or partially blank
Basic Information
Attachments