Sai Sunkari
Sai Sunkari

Reputation: 179

unable to hide rows/ shrink listview items in a list view using visible property and mvvm binding

I have a toggle button and list (which has rows or labels, stack-layout in a grid). Toggle(Switch) and List View are declared in Xaml file where list's Data-cell is generated programmatically in cs file. I need to hide/show this stack layout which is inside the list based on the toggle switch.

I have achieved this by creating a boolean field in the object of the list and assigning it to true when toggle is enabled. And using this field in ISvisiblePraperty of the stacklayout

stacklayout.SetBinding(IsVisibleProperty, new Binding("SubItemSectionVisible", BindingMode.Default, new BooleanConverterForSubItem()));

Now i can see the text inside stacklayout is hiding and visible based on the toggle but the list item size is not shrinking. i have to scroll the list once to see the listview items shrink or expand. Is there a way to achieve this shrink as soon as I click toggle?

This issue is only in iOS, in android it's working fine as expected.

thanks.

Upvotes: 0

Views: 523

Answers (1)

Skin
Skin

Reputation: 11197

This is nothing new with Xamarin Forms iOS. It's been around for a while and to be completely honest with you, I'm not sure if a proper (performant) solution was ever supplied by Xamarin but if it does exist, then ignore the below. :-)

This has existed for a while ...

https://developer.xamarin.com/samples/xamarin-forms/UserInterface/ListView/DynamicUnevenListCells/

... but was always a really non-performant approach. Worth a try, otherwise, I overcame it by creating a custom renderer.

Custom Control

using System;
using Xamarin.Forms;

namespace YourApplication.Controls
{
    public class CustomListView : ListView
    {
        public event EventHandler<int> ItemHeightChangedEvent;

        public void ItemHeightChanged(int index)
        {
            ItemHeightChangedEvent?.Invoke(this, index);
        }
    }
}

Custom iOS Renderer

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using System.ComponentModel;
using YourApplication.Controls;
using Foundation;

[assembly: ExportRenderer(typeof(CustomListView), typeof(YourApplication.iOS.CustomListViewRenderer))]

namespace YourApplication.iOS
{
    public class CustomListViewRenderer : ListViewRenderer
    {
        private CustomListView _formsListView;

        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            _formsListView = Element as CustomListView;

            if (_formsListView == null)
                return;

            _formsListView.ItemHeightChangedEvent += async (object sender, int index) =>
            {
                Control.ReloadRows(new NSIndexPath[] { NSIndexPath.FromRowSection(index, 0) }, UITableViewRowAnimation.Automatic);
            };
        }
    }
}

XAML

<localControls:CustomListView ItemsSource="{Binding Source}" ... >

You'll need to read up on the creation of custom renderers (if you're not already familiar with how to use them) and then all you need to do is, call the ItemHeightChanged method on the item when the cell changes.

Performance can be questionable (hence why only attack the items that have changed) but it worked for me.

I hope that makes sense and more so, I hope it helps.

Upvotes: 0

Related Questions