Hi guys,
I have a ListView
with caching strategy set to RecycleElement
, where each cell has a certain number of context actions implemented with MenuItem
s.
In Android, when the user long presses on a cell the actions are shown and the background color of the selected cell is changed. The problem is that if the user starts scrolling down the list while a cell is selected, after the selected cell goes out of the screen, another cell at the bottom appears with the background color changed, as if it was selected, and this happens repeatedly (if one has enough list items), and this is confusing. The issue is not present when using the RetainElement
caching strategy, to this should be a problem related to the recycling of cells.
Any ideas about to solve this issue?
Well that's definitely a bug. Sorry for the misunderstanding. You should report that bug here: http://bugzilla.xamarin.com
You should attach your project, but before you do you need to make it smaller. To do that just do a clean (or delete all the bin and obj directories) and then delete all of the subdirectories inside the packages directory. Once you do that the whole thing should be well under a MB, and you can attach a zip to the bug report.
Answers
Make sure that the state of your cells is entirely dependent on the BindingContext. Since cells are reused you can't store any state in them directly. For instance, if you are manually setting some property on the cell when it becomes selected to change its appearance then that state will still be present when that cell is reused for some other row. Instead you have to keep the state in the view model (the object in the ItemsSource collection) and use bindings to update the cell's appearance.
If you think you're doing this right then make a small test app that demonstrates the problem and attach it here.
I am aware of that, the problem is that on Android the background color of a cell that has context actions active is defined on Android theme. And in Xamarin it cannot be detected when context are shown and hidden, therefore you cannot really set the background manually, you have to rely on the theme.
I don't understand what any of that has to do with what I said. If you use
RecycleElement
you must define the appearance of your cell purely based on theBindingContext
. If you have a reason you can't possibly do that then you just can't useRecycleElement
.The problem is that I am not setting the background color of the selected cell myself, but it is automatically set when the user long presses on an cell that has context action, so I cannot define it manually based on the binding context.
I've attached a simple test project to clarify the problem. In order to see the issue, long press on whatever element of the list (in order it to show the context action) then try scrolling. You'll see that the background of the selected cell will appear also on other cells
Well that's definitely a bug. Sorry for the misunderstanding. You should report that bug here: http://bugzilla.xamarin.com
You should attach your project, but before you do you need to make it smaller. To do that just do a clean (or delete all the bin and obj directories) and then delete all of the subdirectories inside the packages directory. Once you do that the whole thing should be well under a MB, and you can attach a zip to the bug report.
I have this same issue only on Android starting with Marshmallow. I see the issue when I set the selected listview item with CachingStrategy="RecycleElement". No issues on IOS and no issue when CachingStrategy is retain.
I have a button in the row defined by the data template and when it is clicked I set the selected listview item.
var btnSender = (Button)sender;
var SelectedDocument = btnSender.BindingContext as CabinetApp.ViewModels.DocumentViewModel;
this.lstDocuments.SelectedItem = SelectedDocument;
Now if you start scrolling you see a selected row over and over. Tested with Forms Version 2.0.1.6492-pre1
how to enable caching strategy in xaml ?
@asfend , just create a Custom ListView like that :
public class OptimizedListView : ListView
{
public OptimizedListView() : base(ListViewCachingStrategy.RecycleElement)
{
}
}