Search code examples
c#dynamic-data

How to group and flatten data using DynamicData


I have the following sourcecache object,

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

and then I've grouped the itineraries by date.

_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);

The above code stores the results in the following collection.

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

The ItineraryGroup class is defined as follows,

public class ItineraryGroup : ObservableCollectionExtended<PlainItinerary>
{

}

and I have bound this collection the Xamarin.Forms CollectionView which supports grouping.

But now, I am converting the UI in Xamarin.Android which uses RecyclerView which needs a flat collection.

So, the above DynamicData code, I want to convert to the following structure with minimal changes,

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

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

public ObservableCollectionExtended<BaseItem> Itineraries {get; set;}

Does anybody have an idea how to do it? Thank you.


Solution

  • Used TransformMany and Mege functions to solve the above issue,

    _itineraries
        .Connect()
        .Group(k =>
        {
            if (k.JourneyStartTime.HasValue)
                return new DateTimeOffset(k.JourneyStartTime.Value.Date).ToUnixTimeMilliseconds();
            else
                return -1;
        })
        .TransformMany(k =>
        {
            BaseItineraryItem item = new ItineraryDateItem(k.Key, GuidUtil.GenerateGuid(k.Key.ToString(CultureInfo.InvariantCulture)), this);
            var obs = new ObservableCollection<BaseItineraryItem>() { item };
            var osbSet = obs.ToObservableChangeSet<BaseItineraryItem, string>(m => m.Id);
    
            var groupObservable = k.Cache
                .Connect();
    
            var disposable = groupObservable
                .Merge(osbSet)                        
                .Bind(out var items)
                .Subscribe();
    
            Disposables.Add(disposable);
    
            return items;
        }
        .Sort(SortExpressionComparer<BaseItineraryItem>.Ascending(item => item.Date))
        .ObserveOn(MainThread.AppContext)
        .Bind(ItineraryGroups);