Skip to content

Instantly share code, notes, and snippets.

@vjdw
Created August 17, 2019 20:34
Show Gist options
  • Save vjdw/40b22a64507a6694e8653d06b8655056 to your computer and use it in GitHub Desktop.
Save vjdw/40b22a64507a6694e8653d06b8655056 to your computer and use it in GitHub Desktop.
ASP.NET Core Blazor VirtualList
<!-- To be added to _Host.cshtml -->
<script>
window.blazorHelpers = {
getScrollTop : function (element) {
return element.scrollTop;
},
setScrollTop : function (element, value) {
element.scrollTop = value;
return element.scrollTop;
}
}
</script>
@typeparam TItem
@inject IJSRuntime JSRuntime
<div @ref="scrollContainer" @ref:suppressField style="height: 300px; position: relative; overflow: auto;" @onscroll="HandleScroll">
<div style="height: @(rowHeight*Items.Count())px; width: 1px; position: absolute; top: 0; left: 0;"></div>
@foreach (var virtualRow in VirtualRows)
{
<div style="height: 150px; width: 30px; background-color: gray; position: absolute; top: @(virtualRow.Top)px; left: 0;">@RowTemplate(virtualRow.Item)</div>
}
</div>
<p>@x scrollTop: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
class VirtualRow
{
int rowHeight = 150;
public TItem Item { get; set; }
public int Index { get; set; }
public int Top => Index * rowHeight;
}
IList<VirtualRow> VirtualRows = new List<VirtualRow>();
[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; }
[Parameter]
public IList<TItem> Items { get; set; }
ElementReference scrollContainer;
int currentCount = 0;
int virtualRowCount = 10;
int virtualRowOffset = 0;
int rowHeight = 150;
protected override void OnParametersSet()
{
for (int i = 0; i < virtualRowCount; i++)
{
VirtualRows.Add(new VirtualRow {Item = Items[i], Index = i});
}
}
async Task IncrementCount()
{
currentCount+=10;
await JSRuntime.InvokeAsync<int>("blazorHelpers.setScrollTop", scrollContainer, currentCount);
}
async Task HandleScroll(UIEventArgs args)
{
var scrollTop = await JSRuntime.InvokeAsync<int>("blazorHelpers.getScrollTop", scrollContainer);
currentCount = scrollTop;
if (VirtualRows.First().Top < scrollTop)
{
virtualRowOffset++;
for (int i = 0; i < VirtualRows.Count() - 1; i++)
{
VirtualRows[i] = VirtualRows[i+1];
}
int j = VirtualRows.Count() - 1;
int itemsOffset = virtualRowOffset + j;
VirtualRows[j] = new VirtualRow {Item = Items[itemsOffset], Index = itemsOffset};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment