You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助DynamicData将分组数据转换为扁平集合适配RecyclerView

问题描述

我现有如下SourceCache对象:

private readonly SourceCache<PlainItinerary, string> _itineraries = new SourceCache<PlainItinerary, string>(itinerary => itinerary.ItineraryId);

之前通过DynamicData按日期分组,代码如下:

_itineraries
    .Connect()
    .Group(k =>
    {
        if (k.JourneyStartTime.HasValue)
            return new DateTimeOffset(k.JourneyStartTime.Value.Date).ToUnixTimeMilliseconds();
        else
            return -1;
    })
    .Transform(group => new ItineraryGroup(group, Disposables))
    .Sort(SortExpressionComparer<ItineraryGroup>.Ascending(group => group.Date))
    .ObserveOn(MainThread.AppContext)
    .Bind(ItineraryGroups);

分组结果存储在这个集合中:

public ObservableCollectionExtended<ItineraryGroup> ItineraryGroups {get; set;}

其中ItineraryGroup定义为:

public class ItineraryGroup : ObservableCollectionExtended<PlainItinerary>
{

}

这段代码原本用于绑定Xamarin.Forms的分组CollectionView,但现在要迁移到Xamarin.Android的RecyclerView,而RecyclerView需要扁平集合。我希望最小改动DynamicData代码,转换成以下结构:

public class ItineraryHeaderItem : BaseItem
{
    public DateTimeOffset Date {get; set;}
}

public class ItineraryItem : BaseItem
{
    public PlainItinerary Itinerary {get; set;}
}

public ObservableCollectionExtended<BaseItem> Itineraries {get; set;}
解决方案

你可以通过DynamicData的TransformMany操作,把分组后的结果展开成包含头部和行程项的扁平集合,具体改动如下:

_itineraries
    .Connect()
    // 保留原有分组逻辑
    .Group(k =>
    {
        if (k.JourneyStartTime.HasValue)
            return new DateTimeOffset(k.JourneyStartTime.Value.Date).ToUnixTimeMilliseconds();
        else
            return -1;
    })
    // 基于分组Key转换回日期排序,保证顺序正确
    .Sort(SortExpressionComparer<IGroup<string, PlainItinerary>>.Ascending(group => 
        group.Key != -1 ? DateTimeOffset.FromUnixTimeMilliseconds(group.Key).Date : DateTime.MaxValue.Date))
    // 将每个分组拆分为头部+行程项的组合
    .TransformMany(group => 
    {
        var items = new List<BaseItem>();
        // 为有效日期的分组添加头部
        if (group.Key != -1)
        {
            items.Add(new ItineraryHeaderItem 
            { 
                Date = DateTimeOffset.FromUnixTimeMilliseconds(group.Key) 
            });
        }
        // 添加分组下的所有行程项
        items.AddRange(group.Items.Select(itinerary => new ItineraryItem 
        { 
            Itinerary = itinerary 
        }));
        return items;
    })
    .ObserveOn(MainThread.AppContext)
    // 绑定到新的扁平集合
    .Bind(Itineraries);

关键改动说明:

  • 保留原有的Group和排序逻辑,确保分组规则和展示顺序与之前一致;
  • 用TransformMany替代Transform,将每个分组拆分为一个头部项加多个行程项,实现扁平结构;
  • 排序时基于分组Key转换回日期进行比较,保证头部的顺序正确;
  • 最终绑定到新的ObservableCollectionExtended<BaseItem>集合,适配RecyclerView的扁平数据需求。

如果需要处理无日期的行程(Key=-1),可以根据需求调整头部逻辑,比如添加“无日期”的头部,或者直接跳过头部只显示行程项。

内容的提问来源于stack exchange,提问作者Pravin Patil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:27:33