1

I have this basic virtualized list where I load items using ItemsProvider:

<Virtualize @ref="_listbox" ItemsProvider="ProvideItems">
    <ItemContent>
        <div @key="context"
             class="item-level-@context.level">
             @context.Label
        </div>
    </ItemContent>             
</Virtualize>

private async ValueTask<ItemsProviderResult<Item>> ProvideItems(ItemsProviderRequest request)
{
    using var db = _dbContextFactory.CreateDbContext();
    var query = db.Items
        .GroupBy(e => e.Category)
        .OrderByDescending(e => e.Key)
        .Select((group, index) => new Item
        {
           Label = group.Key, 
           Count = group.Count(),
           Index = index,
        });

    if (_totalCount == null)
    {
        _totalCount = await query.CountAsync(request.CancellationToken);
    }
    var items = await query.Skip(request.StartIndex)
        .Take(request.Count)
        .ToArrayAsync();
    return new ItemsProviderResult<Item>(items, _totalCount.GetValueOrDefault());
}


class ItemModel
{
   int Index {get; set; }
   string Label {get; set;}
   int Count {get; set;}
   // int Level {get; set;} // 0 means root
   // List<ItemModel> Children {get; set;}
}

When user click and item, it should be expanded.

How do I make the items expandable while loading children on demand?

It's non trivial exercise, maybe somebody has already done that. The component should probably track the expanded items, in order to calculate what items should be provided as user scrolls.

Liero
  • 25,216
  • 29
  • 151
  • 297

1 Answers1

0

I realize I am very late to the party here (nearly a year, but no one answered you and I hate that for me) but I figured this out and thought I would share. I have a "tree-like" situation that I render in many rows of in a table where there is collapsing and expanding of parent rows if the users chooses to. I have an IsVisible bool on my object that gets swapped for the children based on the IsExpanded bool which is triggered with a checkbox.

Then in my ItemsProvider I simply do a linq query and filter on the IsVisible property before returning the ItemsProviderResult.

public async ValueTask<ItemsProviderResult<PerformanceClaimMeasurementGridViewModel>> LoadMeasurements(ItemsProviderRequest request) {
  var result = AllMeasurements
    .Where(x => x.IsVisible == true);

  return new ItemsProviderResult<PerformanceClaimMeasurementGridViewModel>(
    result
      .Skip(request.StartIndex)
      .Take(request.Count),
      result.Count()
  );
}
Grandizer
  • 2,819
  • 4
  • 46
  • 75