locked
ListView Grouped Style on iOS RRS feed

  • Question

  • User69071 posted

    I'm wondering if anyone has found a simple way to set the rendered UITableView on iOS to UITableViewStyle.Grouped when using a ListView from Xamarin Forms. It's easy enough to do with TableView as I can set the Intent to "Settings". Ultimately, I'm looking for it because I don't want to show "empty" cells in the table view when there are less items in collection than the screen size.

    I was just curious if there were any solutions out there before I tackled writing a custom renderer to set the style.

    It would be nice if this was just a property on ListView, seems like it could be done with a simple enum.

    Thursday, March 5, 2015 9:44 PM

Answers

  • User107943 posted

    Like you mentioned, a custom renderer is probably the way to go since this style is iOS-unique. Subclass ListView if you don't wan't this renderer to affect all ListViews.

    ``` using System; using UIKit; using Xamarin.Forms.Platform.iOS; using Xamarin.Forms; using MyNamespace;

    [assembly: ExportRenderer(typeof(ListView), typeof(MyListViewRenderer))]

    namespace MyNamespace { public class MyListViewRenderer : ListViewRenderer { protected override void OnElementChanged (ElementChangedEventArgs e) { base.OnElementChanged (e); if ( this.Control != null ) { var tbl = new UITableView (this.Bounds, UITableViewStyle.Grouped) { Source = this.Control.Source }; this.SetNativeControl (tbl); } }

    }
    

    }

    ```

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Saturday, April 4, 2015 5:03 PM

All replies

  • User107943 posted

    Like you mentioned, a custom renderer is probably the way to go since this style is iOS-unique. Subclass ListView if you don't wan't this renderer to affect all ListViews.

    ``` using System; using UIKit; using Xamarin.Forms.Platform.iOS; using Xamarin.Forms; using MyNamespace;

    [assembly: ExportRenderer(typeof(ListView), typeof(MyListViewRenderer))]

    namespace MyNamespace { public class MyListViewRenderer : ListViewRenderer { protected override void OnElementChanged (ElementChangedEventArgs e) { base.OnElementChanged (e); if ( this.Control != null ) { var tbl = new UITableView (this.Bounds, UITableViewStyle.Grouped) { Source = this.Control.Source }; this.SetNativeControl (tbl); } }

    }
    

    }

    ```

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Saturday, April 4, 2015 5:03 PM
  • User156629 posted

    I had this issue recently and thanks to Johan I've been able to find a workarround.

    This is what I added to your solution : - Test if e.NewElement != null to avoid a bug : https://bugzilla.xamarin.com/show_bug.cgi?id=21457 - Do not forget to set the Delegate, or you'll get errors the second time you display the listview

    protected override void OnElementChanged (ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged (e);
        if ( this.Control != null && e.NewElement !=null )
        {
            var tbl = new UITableView (this.Bounds, UITableViewStyle.Grouped)
            {
                Source = this.Control.Source
            };
            this.SetNativeControl (tbl);
        }
    }
    

    edit :

    Dealing with Delegate delete header... and if I don't set Delegate, I have an exeption the second time I display the listview :

    Objective-C exception thrown. Name : NSRangeException Reason: -[UITableView_contentOffsetForScrollingToRowAtIndexPath:atScrollPOsition:] section (0) beyond bounds (0).

    Friday, November 6, 2015 10:02 AM
  • User316224 posted

    @JohanBjrk said: Like you mentioned, a custom renderer is probably the way to go since this style is iOS-unique. Subclass ListView if you don't wan't this renderer to affect all ListViews.

    ``` using System; using UIKit; using Xamarin.Forms.Platform.iOS; using Xamarin.Forms; using MyNamespace;

    [assembly: ExportRenderer(typeof(ListView), typeof(MyListViewRenderer))]

    namespace MyNamespace { public class MyListViewRenderer : ListViewRenderer { protected override void OnElementChanged (ElementChangedEventArgs e) { base.OnElementChanged (e); if ( this.Control != null ) { var tbl = new UITableView (this.Bounds, UITableViewStyle.Grouped) { Source = this.Control.Source }; this.SetNativeControl (tbl); } }

    } }

    ```

    This works, but it kinda messes up the list view . For example, rows doesn't deselect after you've pressed them.

    Friday, May 5, 2017 9:47 AM
  • User57571 posted

    @JohanBjrk Thanks a lot for this!

    Wednesday, February 7, 2018 6:13 PM
  • User301577 posted

    @JohanBjrk I applied your solution, but the background is all gray. In native style, the cell content background is white and the section background is gray. Did you had this problem?

    Tuesday, April 17, 2018 1:39 PM
  • User301272 posted

    @VinciusdaCruzMaia said: @JohanBjrk I applied your solution, but the background is all gray. In native style, the cell content background is white and the section background is gray. Did you had this problem?

    I also have this problem. The list view is grouped but looks wrong in terms of styling and colors.

    Sunday, June 3, 2018 2:17 AM
  • User329721 posted

    A much better and cleaner solution to this problem is to use an iOS platform-specific feature for Xamarin.Forms that allows you to easily set the ListView Group Header Style in XAML (or code behind) in one line as follows:

    <ContentPage ...
                 xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
        <StackLayout Margin="20">
            <ListView ios:ListView.GroupHeaderStyle="Grouped">
                ...
            </ListView>
        </StackLayout>
    </ContentPage>
    
    Thursday, May 30, 2019 10:22 AM