0

I needed to change the color of the selected item in ListView in my Xamarin.Forms application, so I implemented a custom rendered for ViewCell. This worked as required, untill I filled my list with so many elements, that it had to be scrolled. After scroll occurres on the list, it causes a weird bug, where more than one row gets selected (just as if scrolling the list, would change the scope where list looks for selected items and did not reset the selected item). My best guess is that I need to extend my renderer to count for the scrolling of ListView, but I have no idea how to do this. Has anyone encountered similar issues?

Custom Renderer:

[assembly: ExportRenderer(typeof(ExtendedViewCell), typeof(ExtendedViewCellRenderer))]
namespace MyApp.Droid.PlatformSpecific.Renderers
{
    public class ExtendedViewCellRenderer : ViewCellRenderer
    {

        private Android.Views.View _cellCore;
        private Drawable _unselectedBackground;
        private bool _selected;

        protected override Android.Views.View GetCellCore(Cell item,
                                                            Android.Views.View convertView,
                                                            ViewGroup parent,
                                                            Context context)
        {
            _cellCore = base.GetCellCore(item, convertView, parent, context);
            _selected = false;
            _unselectedBackground = _cellCore.Background;
            return _cellCore;
        }

        protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
        {
            base.OnCellPropertyChanged(sender, args);
            if (args.PropertyName == "IsSelected")
            {
                _selected = !_selected;
                if (_selected)
                {
                    var extendedViewCell = sender as ExtendedViewCell;
                    _cellCore.SetBackgroundColor(extendedViewCell.SelectedBackgroundColor.ToAndroid());
                }
                else
                {
                    _cellCore.SetBackground(_unselectedBackground);
                }
            }
        }
    }
}

Custom ViewCell:

public class ExtendedViewCell : ViewCell
{
   public static readonly BindableProperty SelectedBackgroundColorProperty =
   BindableProperty.Create("SelectedBackgroundColor",
                                typeof(Color),
                                typeof(ExtendedViewCell),
                                Color.Default);

   public Color SelectedBackgroundColor
   {
       get { return (Color)GetValue(SelectedBackgroundColorProperty); }
       set { SetValue(SelectedBackgroundColorProperty, value); }
   }
}

Update: I have managed to trace down the issue to beeing caused by different implementation of caching on newer Xamarin.Forms versions. Even the author of the above solution haven't managed to solve this out at this moment: Link

Denis Vitez
  • 608
  • 11
  • 32
  • Of the top of my head on Android you would need to change the `Update` method in the `ViewCellContainer` but I *believe* that is still internal class within ViewCellRenderer as this is where the updated binding happen when the view cell is recycled. You can look at the Forms' source in its GitHub repo to confirm, it should be Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs (have had to modify the source multiple times to handle this "selection" requirement) – SushiHangover Oct 09 '18 at 18:06
  • @SushiHangover so what you are saying is that I should just edit the source of Xamarin.Forms and have it as a special build? – Denis Vitez Oct 09 '18 at 20:39
  • That is what I've done a couple of times (I've worked w/ multiple customers that all maintain their own Xamarin.Forms due to bugs/features/performance enhancements). Another way it to add a container (i.e. a `Frame`) to your Forms' ViewCell, place your cell controls inside of it, and bind the background color of the frame to a property in your ViewModel, it does not look exactly same but that can be "cheap" way to get around it if your model allows for that property to be cached/persisted in some way. – SushiHangover Oct 09 '18 at 20:48

0 Answers0