Xamarin Listview 分组

Posted

技术标签:

【中文标题】Xamarin Listview 分组【英文标题】:Xamarin Listview grouping 【发布时间】:2015-10-28 23:26:20 【问题描述】:

我正在处理 xamarin.froms 中的列表视图。我可以轻松地为每条记录填充列表项:

[
    "cat":1, "name":"alpha",
    "cat":1, "name":"beta",
    "cat":1, "name":"gamma",
    "cat":2, "name":"john",
    "cat":2, "name":"william",
    "cat":2, "name":"smith",
    "cat":2, "name":"steve",
    "cat":3, "name":"abc",
    "cat":3, "name":"xyz"
]

//来自此json源的列表视图中的9个项目

但我想要的是对某个键值的所有项目进行分组,例如"cat",并实现如下效果:

对此的任何建议或方法将不胜感激。

【问题讨论】:

【参考方案1】:

将您的数据分组到集合中,然后将这些集合添加到您的 ListView 中。集合需要是您自己的类,具有用于绑定组的属性。

这是一个演练:

在您的 ListView 上设置分组,包括将每个组绑定到的属性,在本例中为“GroupKey”

    myListView.IsGroupingEnabled = true;
    myListView.GroupDisplayBinding = new Binding("GroupKey"); // See below

然后在组中添加您的数据(例如列表列表)。这通常意味着您需要创建自己的类来显示您的分组,例如:

    public class Grouping<K, T> : ObservableCollection<T>
    
        // NB: This is the GroupDisplayBinding above for displaying the header
        public K GroupKey  get; private set;  

        public Grouping(K key, IEnumerable<T> items)ac
        
            GroupKey = key;
            foreach (var item in items)
                this.Items.Add(item);
        
    

最后,分组添加数据:

    var groups = new ObservableCollection<Grouping<string, MyDataClass>>();

    // You can just pass a set of data in (where "GroupA" is an enumerable set)
    groups.Add(new Grouping<string, MyDataClass>("GroupA", GroupA)); 

    // Or filter down a set of data
    groups.Add(new Grouping<string, MyDataClass>("GroupB", 
        MyItems.Where(a => a.SomeFilter())));

    myListView.ItemSource = groups;

像以前一样将您的单元格绑定到 MyDataClass:

    var cell = new DataTemplate(typeof(TextCell));
    cell.SetBinding(TextCell.TextProperty, "SomePropertyFromMyDataClass");
    cell.SetBinding(TextCell.DetailProperty, "OtherPropertyFromMyDataClass");
    myListView.ItemTemplate = cell;

查看它以了解为什么在 Grouping 类中使用模板 K 而不是字符串、如何自定义标题外观等等:http://motzcod.es/post/94643411707/enhancing-xamarinforms-listview-with-grouping

(归功于@pnavk 答案中的链接)

【讨论】:

【参考方案2】:

在我的环境中,此 url http://motzcod.es/post/94643411707/enhancing-xamarinforms-listview-with-grouping 中的代码不起作用。

不起作用的代码在这里

var partnersSorted = from item in Partners
         orderby item.UserName
         group item by item.UserNameSort into PartnersGroup
         select new Grouping<string, Monkey>(PartnersGroup.Key, PartnersGroup);

MonkeysGrouped = new ObservableCollection<Grouping<string, Monkey>>(partnersSorted);

所以我改了代码。

var sortedPartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
foreach (var item in sortedPartners)

     PartnersGrouped.Add(new PartnersGrouping<string, Item>(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));

你可以这样看。

[https://i.stack.imgur.com/BswPq.png][1]

这是我所有的脚本

项目是合作伙伴

Item.cs

using System;

namespace NewHeats.Models

    public class Item
    
        public string Id
        
            get;
            set;
        
        public string UserName
        
            get;
            set;
        
        public DateTime RegisterDate
        
            get;
            set;
        
        public string Field
        
            get;
            set;
        
        public string Password
        
            get;
            set;
        
        public int Heats
        
            get;
            set;
        
        public string UserNameSort
        
             get
            
                 if (string.IsNullOrWhiteSpace(UserName) || UserName.Length == 0)
                    return "?";

                 return UserName[0].ToString().ToUpper();
            
        
    
 

PartnersGrouping.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace NewHeats.Models

    public class PartnersGrouping<K,T> : ObservableCollection<T>
    
        public K Key  get; private set; 

        public PartnersGrouping(K key,IEnumerable<T> items)
        
            Key = key;
            foreach (var item in items)
            
                this.Items.Add(item);
            
        
    

PartnersViewModel.cs

using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using NewHeats.Models;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Linq;
using System.Diagnostics.Contracts;

namespace NewHeats.ViewModels

    public class PartnersViewModel : BaseViewModel
    
        public Item Me
        
            get;
            set;
        
        public ObservableCollection<Item> Partners  get; set; 
        public ObservableCollection<PartnersGrouping<string, Item>> PartnersGrouped  get; set; 
        public Item SelectedPartner  get; set; 
        public Command LoadPartnersCommand  get; set; 
        public PartnersViewModel()
        
            Title = "Partners";
            Partners = new ObservableCollection<Item>();
            PartnersGrouped = new ObservableCollection<PartnersGrouping<string, Item>>();
            LoadPartnersCommand = new Command(async() =>await ExecuteLoadPartnersCommand());
        

        async Task ExecuteLoadPartnersCommand()
        
            Contract.Ensures(Contract.Result<Task>() != null);
            if (IsBusy)
                return;
            IsBusy = true;
            try
            
                Me = await MockUsrDataStore.GetItemAsync("naoto");                           
                Partners.Clear();
                var allfriends = await MockFriDataStore.GetItemsAsync(true);                 
                var myFriends = allfriends.Where(x => x.MyId == Me.Id);                      
                var allUsers = await MockUsrDataStore.GetItemsAsync(true);                   

                foreach (var item in myFriends)
                
                    var partner = allUsers.FirstOrDefault(x => x.Id == item.FriendId);       
                    if (partner!=null)
                    
                        Partners.Add(partner);
                    
                
                var sortedpartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
                foreach (var item in sortedpartners)
                
                     PartnersGrouped.Add(new PartnersGrouping<string, Item>(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));
                
            
            catch (Exception ex)
            
                Debug.WriteLine(ex);
            
            finally
            
                IsBusy = false;
            
        
    

PartnerPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="NewHeats.Views.PartnersPage" xmlns:vm="clr-namespace:NewHeats.ViewModels" xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin" Title="Binding Title">
    <ContentPage.Resources>
        <ResourceDictionary>
            <!--Page Level Resources: Compatibile with Xamarin Live Player -->
            <Color x:Key="Primary">#2196F3</Color>
            <Color x:Key="Accent">#96d1ff</Color>
            <Color x:Key="LightTextColor">#999999</Color>
        </ResourceDictionary>
    </ContentPage.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ScrollView Grid.Row="0">
            <StackLayout Orientation="Vertical" Padding="16,40,16,40" Spacing="10">
                <ListView ItemsSource="Binding PartnersGrouped"
                          HasUnevenRows="true"
                          VerticalOptions="FillAndExpand"
                          IsPullToRefreshEnabled="true"
                          CachingStrategy="RecycleElement"
                          IsRefreshing="Binding IsBusy, Mode=OneWay"
                          RefreshCommand="Binding LoadPartnersCommand"
                          ItemSelected="Handle_ItemSelected"
                          SelectedItem="Binding SelectedPartner"
                          GroupDisplayBinding="Binding Key"
                          IsGroupingEnabled="true"
                          GroupShortNameBinding="Binding Key">
                    <ListView.GroupHeaderTemplate>
                        <DataTemplate>
                            <ViewCell Height="25">
                                <StackLayout VerticalOptions="FillAndExpand"
                                             Padding="5"
                                             BackgroundColor="#3498DB">
                                       <Label Text="Binding Key" TextColor="White" VerticalOptions="Center"/>
                                </StackLayout>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.GroupHeaderTemplate>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="60"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="60"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <controls:CircleImage Source="husky.jpg"
                                                          Aspect="AspectFill"
                                                          Grid.Column="0"
                                                          Grid.Row="0"
                                                          WidthRequest="60"
                                                          HeightRequest="60">
                                    </controls:CircleImage>
                                       <StackLayout Orientation="Vertical" Grid.Column="1">
                                           <Label Text="Binding UserName" VerticalTextAlignment="Center"/>
                                      </StackLayout>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>
        </ScrollView>
    </Grid>
</ContentPage>

谢谢!!

【讨论】:

【参考方案3】:

Xamarin.Forms ListView 确实支持分组。请查看他们的文档http://developer.xamarin.com/guides/cross-platform/xamarin-forms/user-interface/listview/customizing-list-appearance/#Grouping 以了解如何使用它。

【讨论】:

以上是关于Xamarin Listview 分组的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin表单 - 如何使用标题生成iOS ListView本机分组样式?

Xamarin使用ListView开启分组视图Cell数据展示bug处理

从自定义列表 Xamarin 中设置所选列表视图项的背景颜色

Xamarin 表单:分组 ObservableCollection

按特定值对 ListView 或 ListView.ItemTemplate 进行排序

Xamarin 表单 ListView 绑定