@attribute [CascadingTypeParameter(nameof(T))]
@typeparam T
@ChildContent
@code {
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public required Func> DataSource { private get; set; }
public T Data { get; private set; }
public ComponentState ComponentState { get; private set; } = ComponentState.Loading;
public event EventHandler? OnStateChanged;
private bool reloadRequested = false;
private Task? loadTask = null;
private object loadLock = new();
protected override void OnInitialized() => Load();
public void Load() {
lock(loadLock) {
reloadRequested = true;
if(loadTask is null || loadTask.IsCompleted) {
//loadTask = Task.Run(LoadInternalAsync);
loadTask = LoadInternalAsync();
}
}
}
private async Task LoadInternalAsync() {
while(true) {
lock(loadLock) {
if(!reloadRequested)
break;
reloadRequested = false;
}
//ComponentState = ComponentState.Loading;
//await InvokeAsync(() => OnStateChanged?.Invoke(this, EventArgs.Empty));
//await InvokeAsync(() => StateHasChanged());
try {
Data = await DataSource.Invoke();
ComponentState = ComponentState.Loaded;
} catch {
ComponentState = ComponentState.Error;
}
await InvokeAsync(() => OnStateChanged?.Invoke(this, EventArgs.Empty));
await InvokeAsync(() => StateHasChanged());
}
}
}