You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor带返回结果的确认对话框问题:无法等待用户输入

Blazor 实现类似 JavaScript confirm 的异步确认对话框

你的代码无法等待用户输入的核心原因是PromptAsync方法在显示模态框后立即返回了confirmed变量的初始值,没有等待用户点击按钮的操作完成。要实现类似JS中confirm的阻塞式异步等待效果,需要借助TaskCompletionSource来创建一个可等待的任务,直到用户交互完成后再结束任务并返回结果。

解决方案

关键修改点

  • 使用TaskCompletionSource<bool>控制异步任务的完成时机
  • 移除原生Bootstrap的data-dismiss="modal",改用Blazor事件统一控制模态框状态,避免JS与Blazor状态冲突
  • 实现IDisposable清理未完成任务,防止内存泄漏
  • 所有关闭对话框的路径(叉号、按钮)都统一处理结果并完成任务

修改后的完整组件代码

@using System.Threading
@implements IDisposable

<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header blue-dlg">
                <p class="modal-title">@Title</p>
                <button type="button" class="close" aria-label="Close" @onclick="() => CloseModal(false)">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body dlg-validation">
                <p>@Message</p>
            </div>
            <div class="modal-footer justify-content-center">
                @{
                    if (DT == DialogTypes.Alert)
                    {
                        <button type="button" class="btn btn-secondary" @onclick="() => CloseModal(false)">Close</button>
                    }
                    else if (DT == DialogTypes.Prompt)
                    {
                        <button type="button" class="btn btn-secondary" @onclick="() => OnConfirm(true)">Yes</button>
                        <button type="button" class="btn btn-secondary" @onclick="() => OnConfirm(false)">No</button>
                    }
                }
            </div>
        </div>
    </div>
</div>

@if (ShowBackdrop)
{
    <div class="modal-backdrop fade @ModalClass" style="display: @ModalDisplay"></div>
}

@code {
    public enum DialogTypes 
    {
        Alert = 0,
        Prompt
    }

    private DialogTypes DT = DialogTypes.Alert;
    private TaskCompletionSource<bool>? _tcs;
    public Guid Guid = Guid.NewGuid();
    public string ModalDisplay = "none;";
    public string ModalClass = "";
    public bool ShowBackdrop = true;

    public string Title { get; set; } = string.Empty;
    public string Message { get; set; } = string.Empty;

    public Task<bool> PromptAsync(string message, string title)
    {
        // 重置并创建新的任务源
        _tcs?.TrySetCanceled();
        _tcs = new TaskCompletionSource<bool>();

        DT = DialogTypes.Prompt;
        Title = title;
        Message = message;
        ModalDisplay = "block;";
        ModalClass = "show";
        StateHasChanged();

        return _tcs.Task;
    }

    public async Task AlertAsync(string message, string title)
    {
        Title = title;
        Message = message;
        ModalDisplay = "block;";
        ModalClass = "show";
        StateHasChanged();
    }

    private async Task CloseModal(bool isConfirmed)
    {
        ModalClass = "";
        await Task.Delay(250); // 等待关闭动画完成
        ModalDisplay = "none;";
        StateHasChanged();

        // 完成任务并返回用户操作结果
        _tcs?.TrySetResult(isConfirmed);
        _tcs = null;
    }

    private async Task OnConfirm(bool confirm)
    {
        await CloseModal(confirm);
    }

    public void Dispose()
    {
        // 组件销毁时清理未完成任务
        _tcs?.TrySetCanceled();
        _tcs = null;
    }
}

使用示例

在父组件中注入并调用,即可像JS的confirm一样等待用户输入:

@inject ConfirmDialog Dialog

<button @onclick="HandleDelete">删除数据</button>

@code {
    private async Task HandleDelete()
    {
        bool result = await Dialog.PromptAsync("确定要删除这条数据吗?", "确认删除");
        if (result)
        {
            // 执行删除逻辑
        }
    }
}

内容的提问来源于stack exchange,提问作者Single Step Debugger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 20:05:14