我们注意到,在Blazor服务器端应用程序中,用户可以无意地多次单击按钮。如何使用Blazor框架中提供的选项来防止这种情况发生?
只要将按钮的文本更改为“正在处理...”,只要他们点击按钮就可以满足我们的要求,但是我不确定如何实现。点击事件的处理程序需要花费几秒钟的时间。
有指针吗?
答案 0 :(得分:3)
您可能会遇到以下两个问题之一或全部都出现:
对于长期运行的任务,您可以尝试以下解决方案。我尚未测试,里程可能会有所不同。
<button disabled=@IsTaskRunning @onclick="DispatchTask">Submit</button>
@code {
bool IsTaskRunning = false;
async void DispatchTask()
{
IsTaskRunning = true;
await DoLongWork();
IsTaskRunning = false;
StateHasChanged();
}
Task DoLongWork()
{
return Task.Delay(6000);
}
}
答案 1 :(得分:1)
这最适合与异步处理程序方法配合使用,例如
async Task DispatchTask()
{
IsTaskRunning = true;
await DoLongWork();
IsTaskRunning = false;
// StateHasChanged(); // called automatically
}
这来自@EdCharbeneau的答案,但请注意,它现在是一种async task
方法。
但这仅在DoLongWork()确实异步时才有效。这意味着它必须尽早进行一些实际的异步I / O。您不能总是说,一个等待的方法可能(有时)完全或很大程度上同步执行。发生这种情况时,您的GUI不会更新。
假设DoWork()方法看起来更像
Task DoLongWork()
{
Thread.Sleep(6000); // synchronous
return Task.CompletedTask;
}
这将仍然禁用该按钮:
async Task DispatchTask()
{
IsTaskRunning = true;
await Task.Delay(1); // allow the GUI to catch up
await DoLongWork(); // fake async
IsTaskRunning = false;
}
这实际上与WinForm的DoEvents()有点相似,但是并不那么糟糕。在WPF中,您还必须延迟欺骗。
答案 2 :(得分:0)
通用解决方案怎么样? SpinnerButton
可以轻松地对其进行编辑以使用标准按钮。 Generate a SVG animation here.
(Radzen和Loading.io都是免费的)
<RadzenButton Text="@(IsProcessing ? null : Text)" Image="@(IsProcessing ? Spinner : null)" Disabled="@IsProcessing" @attributes="@AdditionalAttributes" />
@code {
[Parameter]
public string Text { get; set; } = string.Empty;
[Parameter]
public string Spinner { get; set; } = "/images/spinner-button.svg";
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
public bool IsProcessing { get; private set; }
[Parameter]
public EventCallback OnSubmit { get; set; }
public async Task FormSubmitAsync()
{
if (IsProcessing) { return; }
IsProcessing = true;
try
{
await OnSubmit.InvokeAsync(null);
}
finally
{
IsProcessing = false;
}
}
}
像这样使用
<EditForm OnValidSubmit="@SubmitAsync">
<SpinnerButton @ref="ButtonRef" style="width:150px" Text="Login"
ButtonType="@((Radzen.ButtonType)ButtonType.Submit)"
ButtonStyle="@((Radzen.ButtonStyle)ButtonStyle.Primary)"
OnSubmit="LogInAsync" />
</EditForm>
@code {
public SpinnerButton? ButtonRef { get; set; }
public async Task SubmitAsync() => await ButtonRef!.FormSubmitAsync().ConfigureAwait(false);
public async Task LogInAsync()
{
// Get stuff done!
}
}
答案 3 :(得分:-2)
private Dictionary<string, string> control = new Dictionary<string, string>();
function click(){
lock (control)
{
if (!control.ContainsKey("click"))
{
control.Add("click", "executing");
}
else
{
if (control["click"] == "executing")
{
//Double click detected
return;
}
else
{
control["click"] = "executing";
}
}
}
//Do usual stuffs here
lock (control)
{
control["click"] = "";
}
}