如何在Blazor中单击后立即禁用/隐藏按钮?

时间:2019-12-05 18:23:41

标签: blazor blazor-server-side

我们注意到,在Blazor服务器端应用程序中,用户可以无意地多次单击按钮。如何使用Blazor框架中提供的选项来防止这种情况发生?

只要将按钮的文本更改为“正在处理...”,只要他们点击按钮就可以满足我们的要求,但是我不确定如何实现。点击事件的处理程序需要花费几秒钟的时间。

有指针吗?

4 个答案:

答案 0 :(得分:3)

您可能会遇到以下两个问题之一或全部都出现:

  1. 延迟是一个问题。确保您在启用Web套接字的情况下托管应用程序。该设置取决于主机,例如:Azure App Server在设置下具有用于Web套接字的简单打开/关闭旋钮。请参阅此博客文章http://blazorhelpwebsite.com/Blog/tabid/61/EntryId/4349/Deploying-A-Server-Side-Blazor-Application-To-Azure.aspx
  2. 中的最后一步
  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"] = "";
    }

}