Skip to content

Commit 202bf61

Browse files
committed
Restructured + infinite scroll
1 parent 8d16b79 commit 202bf61

File tree

15 files changed

+1553
-166
lines changed

15 files changed

+1553
-166
lines changed

src/Components/Components/ref/Microsoft.AspNetCore.Components.netcoreapp.cs

Lines changed: 646 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.AspNetCore.Components.Virtualization
8+
{
9+
/// <summary>
10+
/// Describes a helper for detecting and relaying virtualization events.
11+
/// </summary>
12+
public interface IVirtualizationHelper : IAsyncDisposable
13+
{
14+
/// <summary>
15+
/// Performs platform-specific initialization.
16+
/// </summary>
17+
/// <param name="topSpacer">The <see cref="ElementReference"/> representing the top spacer.</param>
18+
/// <param name="bottomSpacer">The <see cref="ElementReference"/> representing the bottom spacer.</param>
19+
/// <returns>The <see cref="ValueTask"/> associated with the completion of this operation.</returns>
20+
ValueTask InitAsync(ElementReference topSpacer, ElementReference bottomSpacer);
21+
22+
/// <summary>
23+
/// Invoked when the top spacer becomes visible.
24+
/// </summary>
25+
event EventHandler<SpacerEventArgs> TopSpacerVisible;
26+
27+
/// <summary>
28+
/// Invoked when the bottom spacer becomes visible.
29+
/// </summary>
30+
event EventHandler<SpacerEventArgs> BottomSpacerVisible;
31+
}
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNetCore.Components.Virtualization
5+
{
6+
/// <summary>
7+
/// Describes services enabling platform-specific virtualization.
8+
/// </summary>
9+
public interface IVirtualizationService
10+
{
11+
/// <summary>
12+
/// Creates a helper used for detecting and relaying virtualization events.
13+
/// </summary>
14+
/// <returns></returns>
15+
IVirtualizationHelper CreateVirtualizationHelper();
16+
}
17+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Concurrent;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
11+
namespace Microsoft.AspNetCore.Components.Virtualization
12+
{
13+
/// <summary>
14+
/// Provides functionality for rendering a virtualized, infinite list of items.
15+
/// </summary>
16+
/// <typeparam name="TItem">The <c>context</c> type for the items being rendered.</typeparam>
17+
public sealed class InfiniteScroll<TItem> : VirtualizeBase<TItem>
18+
{
19+
private readonly ConcurrentQueue<TItem> _loadedItems = new ConcurrentQueue<TItem>();
20+
21+
private int _fetchingItems;
22+
23+
protected override int ItemCount => InfiniteScrollFooter == null ? _loadedItems.Count : _loadedItems.Count + 1;
24+
25+
/// <summary>
26+
/// Gets or sets the list item template.
27+
/// </summary>
28+
[Parameter]
29+
public RenderFragment<TItem> Item { get; set; } = default!;
30+
31+
/// <summary>
32+
/// Gets or sets the infinite scroll footer template.
33+
/// </summary>
34+
[Parameter]
35+
public RenderFragment? InfiniteScrollFooter { get; set; }
36+
37+
/// <summary>
38+
/// Gets or sets the function that provides items for the inifinite scroll.
39+
/// </summary>
40+
[Parameter]
41+
public Func<Range, Task<IEnumerable<TItem>>> ItemsProvider { get; set; } = default!;
42+
43+
/// <summary>
44+
/// The batch size in which items are fetched.
45+
/// </summary>
46+
[Parameter]
47+
public int ItemBatchSize { get; set; }
48+
49+
protected override IEnumerable<RenderFragment> GetItems(int start, int count)
50+
{
51+
if (start + count >= _loadedItems.Count)
52+
{
53+
// Fetch more items if we're not already
54+
FetchItemsAsync();
55+
56+
var items = _loadedItems.Skip(start).Select(item => Item(item));
57+
58+
return InfiniteScrollFooter == null ? items : items.Append(InfiniteScrollFooter);
59+
}
60+
else
61+
{
62+
return _loadedItems.Skip(start).Take(count).Select(item => Item(item));
63+
}
64+
}
65+
66+
private void FetchItemsAsync()
67+
{
68+
if (Interlocked.Exchange(ref _fetchingItems, 1) == 0)
69+
{
70+
ItemsProvider(new Range(_loadedItems.Count, _loadedItems.Count + ItemBatchSize)).ContinueWith(t =>
71+
{
72+
foreach (var item in t.Result)
73+
{
74+
_loadedItems.Enqueue(item);
75+
}
76+
77+
_fetchingItems = 0;
78+
79+
InvokeAsync(() => StateHasChanged());
80+
});
81+
}
82+
}
83+
}
84+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNetCore.Components.Virtualization
7+
{
8+
/// <summary>
9+
/// Describes an event involving a spacer in a virtualized list.
10+
/// </summary>
11+
public class SpacerEventArgs : EventArgs
12+
{
13+
/// <summary>
14+
/// The new size of the spacer.
15+
/// </summary>
16+
public float SpacerSize { get; }
17+
18+
/// <summary>
19+
/// The current size of the spacer's container.
20+
/// </summary>
21+
public float ContainerSize { get; }
22+
23+
/// <summary>
24+
/// Instantiates a new <see cref="SpacerEventArgs"/> instance.
25+
/// </summary>
26+
/// <param name="spacerSize">The new size of the spacer.</param>
27+
/// <param name="containerSize">The current size of the spacer's container.</param>
28+
public SpacerEventArgs(float spacerSize, float containerSize)
29+
{
30+
SpacerSize = spacerSize;
31+
ContainerSize = containerSize;
32+
}
33+
}
34+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
7+
namespace Microsoft.AspNetCore.Components.Virtualization
8+
{
9+
/// <summary>
10+
/// Provides functionality for rendering a virtualized, fixed-size list of items.
11+
/// </summary>
12+
/// <typeparam name="TItem">The <c>context</c> type for the items being rendered.</typeparam>
13+
public sealed class Virtualize<TItem> : VirtualizeBase<TItem>
14+
{
15+
protected override int ItemCount => Items.Count;
16+
17+
/// <summary>
18+
/// Gets or sets the content template for list items.
19+
/// </summary>
20+
[Parameter]
21+
public RenderFragment<TItem>? ChildContent { get; set; }
22+
23+
/// <summary>
24+
/// Gets or sets the collection of items used to generate the list.
25+
/// </summary>
26+
[Parameter]
27+
public ICollection<TItem> Items { get; set; } = default!;
28+
29+
protected override IEnumerable<RenderFragment> GetItems(int start, int count)
30+
{
31+
return ChildContent == null ?
32+
Enumerable.Empty<RenderFragment>() :
33+
Items.Skip(start).Take(count).Select(item => ChildContent.Invoke(item));
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)