ListView Grouping : Example Please

LisanneFogetLisanneFoget CAUniversity

Can anyone explain to me how to do grouping within the Forms ListView? It's not quite apparent how it is supposed to work. Thank you very much.

Posts

  • JasonAwbreyJasonAwbrey USInsider, University, Developer Group Leader mod

    DealerLoads is a List<Dealer>, where Dealer is IEnumerable

                this.ItemsSource = load.DealerLoads;
                this.IsGroupingEnabled = true;
                this.GroupDisplayBinding = new Binding ("Dealer.Name");
                this.GroupHeaderTemplate = null;
    
                this.ItemTemplate = new DataTemplate (typeof(TextCell)) 
                    { Bindings = {
                        { TextCell.TextProperty, new Binding("Description") }, 
                        { TextCell.DetailProperty, new Binding("SubDescription") } 
                        }
                    };
    
  • ToddSouthenToddSouthen USMember

    There's also the Xamarin LabelledSectionsList sample that might help.

  • rtraversortraverso USMember

    the notes it was usefull
    Thanks

  • tkowalczyktkowalczyk PLMember, University ✭✭

    @JamesMontemagno has prepared a really nice solution for this here:
    http://motzcod.es/post/94643411707/enhancing-xamarin-forms-listview-with-grouping
    have a look and get this working!

  • RaphaelSchindlerRaphaelSchindler USMember ✭✭✭

    @tkowalczyk Ah that's where most of my code comes from.

  • tkowalczyktkowalczyk PLMember, University ✭✭

    @RaphaelSchindler yeah I noticed that and would like to add the source ;)

  • AbdulbashaAbdulbasha USMember ✭✭

    Hai everyone, here as per my requirement i want to add the selected contacts into groups like family group, college friends group, Office friends group like this. Can anyone share the Source code in xamarin PCL project only. Thanks in advance

  • MonteHansenMonteHansen USUniversity ✭✭

    Thank you Kraig for that most important distinction about binding to a collection of collections. I have read numerous posts on this subject and for whatever reasons that distinction escaped me until reading your post.

  • mani1010mani1010 USMember

    Hi @RaphaelSchindler ,

    Thanks for the post.

    Could you let me know how to place custom Group header(multiple) with your approach.

  • cassionandicassionandi USMember ✭✭

    @KraigBrockschmidt-MSFT said:
    I worked through the examples above with XAML and had a couple more notes to add.

    First, it's important that the ListView.ItemsSource is a collection of collections, as in the following hierarchy (I'm using ObservableCollection assuming that most people will want to data-bind to these):

    public class Item
    {
        public String Title { get; private set; }
        public String Description {get; private set; }
    
        public Item(String title, String description)
        {
            Title = title;
            Description = description;
        }    
    
        // Whatever other properties
    }
    
    // It's essential that each group directly derives from a collection of the individual items.
    // It does *not* work to have a group that contains an item collection property, as the ListView
    // won't find the items.
    public class Group : ObservableCollection<Item>
    {
            public String Name { get; private set; }        
            public String ShortName { get; private set; }
    
            public Group(String Name, String ShortName)
            {
                this.Name = Name;                     
                this.ShortName = ShortName;   
            }
    
        // Whatever other properties
    }
    
    // Populating the groups
    ObservableCollection<Group> groupedItems = new ObservableCollection<Group>;
    
    //Repeat for each group. This builds the top-level collection
    Group group = new Group("First Group", "1");     
    groupedItems.Add(group);  
    
    // Repeat for each item in a group. This builds the second-level collections
    Item item = new Item("First Item", "First Item Description");  
    group.Add(item);                    
    

    Assume now you have a viewmodel class called PageViewModel that PageViewModel.GroupedItems is the groupedItems collection created above. The XAML for a Xamarin.Forms.ContentPage with the ListView is then as follows:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:MyApp;assembly=MyApp"
                 x:Class="MyApp.MyPage">
    
      <ContentPage.BindingContext>
        <local:PageViewModel />
      </ContentPage.BindingContext>
     
      <ListView ItemsSource="{ Binding GroupedItems }"
                IsGroupingEnabled="true"
                GroupDisplayBinding="{ Binding Name }"
                GroupShortNameBinding ="{ Binding ShortName }"
                ItemTapped="OnItemTapped">
        <ListView.ItemTemplate>
          <DataTemplate>
            <TextCell Text="{ Binding Title }" Detail="{ Binding Description }" />
            
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
         
    </ContentPage>    
    

    A note about binding contexts:

    • The context for the page is PageViewModel, thus ListView.ItemsSource gets bound to PageViewModel.GroupedItems.

    • That ItemsSource then automatically becomes the binding context for GroupDisplayBinding and GroupShortNameBinding.

    • Similarly, within the ItemTemplate, the binding context is automatically set to the current item being rendered.

    And for completeness the OnItemTapped method in the code-behind would be:

    void OnItemTapped(Object sender, ItemTappedEventArgs e)
    {
        //Cast to the data type of the actual item
        var dataItem = (Item)(e.Item);
                    
        //Do what you need
    }
    

    Your example help me a lot sir. Thank you!

  • kkopkkop PLMember
    edited October 2016

    Is it possible to group listview two times?
    My goal is to show list of cars (for example):

    • BMW

      • 3
        -- 316i
        -- 318i
        -- 320d
      • 5
        -- 520i
        -- 530d
    • VW

      • Golf
        -- 1.5
        -- 2.0

    I was trying to achieve it like this:

    IEnumerable<GroupItem<string, GroupItem<int, Car>>> GetCars();
    
    <ListView ItemsSource="{Binding Cars}"
              GroupShortNameBinding="{Binding Key}"
                GroupDisplayBinding="{Binding Key}"
                IsGroupingEnabled="True"
                SeparatorVisibility="Default">
        <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
              <ListView ItemsSource="{Binding}"
                GroupShortNameBinding="{Binding Key}"
                GroupDisplayBinding="{Binding Key}"
                IsGroupingEnabled="True"
                SeparatorVisibility="Default">
    
                <ListView.ItemTemplate>
                  <DataTemplate>
                    <ViewCell>
                        <Label Text="{Binding Engine}"/>
                    </ViewCell>
                  </DataTemplate>
                </ListView.ItemTemplate>
    
              </ListView>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    

    My idea was to draw ListView inside ListView's DataTemplate but

    • is that possible?
    • how can I get items in DataTemplate? I guess this is wrong:
    <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
              <ListView ItemsSource="{Binding}"
    (...)
    
  • ShawnLee.4281ShawnLee.4281 USMember ✭✭

    @Kraig Brockschmidt

    much thanks!

  • @KraigBrockschmidt-MSFT
    Thanks for the example.. I have a question regarding your NOTE...

    // It's essential that each group directly derives from a collection of the individual items.
    // It does not work to have a group that contains an item collection property, as the ListView
    // won't find the items.

    Is this still a problem in XF?

    I am using SQLite and can't have my models derive from an ObservableCollection<> or a List<> since this is not supported in SQLite. That's why I tried using a Collection property which is not recognised by the ListView anymore at all it seems. :(

    Does anybody have a suggestion or better an example how to use ListView Grouping using SQLite.

    Thanks a lot!

    Cheers

  • KraigBrockschmidt-MSFTKraigBrockschmidt-MSFT USMember, University ✭✭

    @SaschaMartinetz I don't know, unfortunately, as I haven't been working with Xamarin for some time now.

  • @KraigBrockschmidt-MSFT
    Thanks anyway.. just had an idea but have to try first if that works. ;)

  • Solved it with a little workaround...
    Just created a second model (a duplicate of the first group class) only for grouping my items. This class can derive now (just as described by Kraig) from ObservableCollection because it does not map any SQLite tables.

    The first (original) class now holds explicitly the persistent group data from my DB and I deleted the OL property (mentioned earlier) because it's not needed anymore.

    Works like a charme... ;)

    Thanks again.. cheers

  • AndyDentAndyDent AUMember ✭✭

    For anyone using Realm, or possibly interested in how they do it, they released a little add-on for supporting this with a couple of lines of code. Realm.GroupedCollection

  • AdrianGhiAdrianGhi USMember ✭✭

    @tkowalczyk said:
    @JamesMontemagno has prepared a really nice solution for this here:
    http://motzcod.es/post/94643411707/enhancing-xamarin-forms-listview-with-grouping
    have a look and get this working!

    How can I achieve the same thing in Android like in iOS? Because in Android, this header is not sticky header like in iOS.. \

  • MartinedoMartinedo Member ✭✭

    @AdrianGhi have you solved the sticky headers on Android somehow?

  • AdrianGhiAdrianGhi USMember ✭✭

    @Martinedo no, I didn't find any solution and I didn't manage to do this sticky header... We just renounced at the idea..

Sign In or Register to comment.