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">×</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
相关产品推荐
相关产品推荐

