提问人:Single Step Debugger 提问时间:6/13/2023 更新时间:6/14/2023 访问量:357
Blazor 的确认对话框,其中包含对话框结果
Confirmation dialog for Blazor with dialog result
问:
我正在尝试在 Blazor 中创建类似于我们在 JS 中的通用提示 dlg。这是我所追求的行为:
我们提示 bool 结果 = await JS。InvokeAsync(“确认”, $“你确定吗?”);
我们等待结果,直到用户单击“是”或“否”。
if(结果) { 做 }
我创建了对话框,但它从不等待用户的输入。下面是带有 Bootstrap 模式的对话框组件:
@using System.Threading
<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay" aria-hidden="true" data-toggle="modal">
<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" data-dismiss="modal" aria-label="Close" @onclick="() => CloseModal()">
<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" data-dismiss="modal" @onclick="() => CloseModal()">Close</button>
}
else if (DT == DialogTypes.Prompt)
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => OnConfirm(true)">Yes</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => OnConfirm(false)">No</button>
}
}
</div>
</div>
</div>
</div>
<div class="modal-backdrop fade @ModalClass" style="display: @ModalDisplay"></div>
@code {
public enum DialogTypes
{
Alert = 0,
Prompt
}
private DialogTypes DT = DialogTypes.Alert;
private bool confirmed = false;
public Guid Guid = Guid.NewGuid();
public string ModalDisplay = "none;";
public string ModalClass = "";
public bool ShowBackdrop = false;
public string Title { get; set; }
public string Message { get; set; }
public async Task<bool> PromptAsync(string message, string title)
{
DT = DialogTypes.Prompt;
Title = title;
Message = message;
ModalDisplay = "block;";
await Task.Delay(100);
ModalClass = "show";
StateHasChanged();
return confirmed;
}
public async Task AlertAsync(string message, string title)
{
Title = title;
Message = message;
ModalDisplay = "block;";
await Task.Delay(100);
ModalClass = "show";
StateHasChanged();
}
public async Task CloseModal()
{
ModalClass = "";
await Task.Delay(250);
ModalDisplay = "none;";
StateHasChanged();
}
private async Task OnConfirm(bool confirm)
{
confirmed = confirm;
await CloseModal();
}
}
答:
0赞
MrC aka Shaun Curtis
6/14/2023
#1
您需要生成一个手动控制的运行任务,并将其交还给调用方。然后,他们可以等待任务,并且只有在您关闭对话框并将任务设置为“已完成”时才能自行完成。
为此,您可以使用类的服务。TaskCompletionSource
以下是在对话框中执行此操作的方法。
@using System.Threading
<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay" aria-hidden="true" data-toggle="modal">
<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>
@{
if (DT == DialogTypes.Alert)
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => CloseModal()">
<span aria-hidden="true">×</span>
</button>
}
else if (DT == DialogTypes.Prompt)
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @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" data-dismiss="modal" @onclick="() => CloseModal()">Close</button>
}
else if (DT == DialogTypes.Prompt)
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => CloseModal(true)">Yes</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => CloseModal(false)">No</button>
}
}
</div>
</div>
</div>
</div>
<div class="modal-backdrop fade @ModalClass" style="display: @ModalDisplay"></div>
@code {
public enum DialogTypes
{
Alert = 0,
Prompt
}
private DialogTypes DT = DialogTypes.Alert;
private bool confirmed = false;
public Guid Guid = Guid.NewGuid();
public string ModalDisplay = "none;";
public string ModalClass = "";
public bool ShowBackdrop = false;
public string Title { get; set; }
public string Message { get; set; }
private TaskCompletionSource<bool> _alertTaskCompletionSource = new();
private Task<bool> _alertTask = Task.FromResult(true);
private TaskCompletionSource _taskCompletionSource = new();
private Task _task = Task.CompletedTask;
public Task<bool> PromptAsync(string message, string title)
{
// Check if the modal is already running and exit if it is
if (!_alertTask.IsCompleted || !_task.IsCompleted)
return Task.FromResult(false);
DT = DialogTypes.Prompt;
Title = title;
Message = message;
ModalDisplay = "block;";
ModalClass = "show";
StateHasChanged();
_alertTaskCompletionSource = new();
_alertTask = _alertTaskCompletionSource.Task;
return _alertTask;
}
public Task AlertAsync(string message, string title)
{
// Check if the modal is already running and exit if it is
if (!_alertTask.IsCompleted || !_task.IsCompleted)
return Task.CompletedTask;
Title = title;
Message = message;
ModalDisplay = "block;";
ModalClass = "show";
StateHasChanged();
_taskCompletionSource = new();
_task = _taskCompletionSource.Task;
return _alertTask;
}
public void CloseModal()
{
ModalClass = "";
ModalDisplay = "none;";
StateHasChanged();
if (!_task.IsCompleted)
_taskCompletionSource.SetResult();
}
public void CloseModal(bool result)
{
ModalClass = "";
ModalDisplay = "none;";
StateHasChanged();
_alertTaskCompletionSource.SetResult(result);
}
}
这里有一个测试页面来演示它的工作原理:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<div>
<button class="btn btn-primary" @onclick=this.OpenModal>Open Dialog</button>
</div>
<MyModal @ref=_modal />
<div class="bg-dark text-white m-2 p-2">
<pre>Result = @_result</pre>
</div>
@code {
private MyModal? _modal;
private bool _result;
private async Task OpenModal()
{
if (_modal is not null)
{
_result = await _modal.PromptAsync("Do You Really Want To", "Exit Check");
// Do whatever you want with the result
}
}
}
评论
0赞
Single Step Debugger
6/14/2023
经过测试并有效。我刚刚从示例中清除了我的标记和消息中的一个小错误,因此我们有一个完整的组件包含您的解决方案:
0赞
Single Step Debugger
6/14/2023
#2
这是 MrC aka Shaun Curtis 解决方案,没有我对完整组件的错误标记: 固定标记:
<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay" aria-hidden="true" data-toggle="modal">
<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>
@{
if (DT == DialogTypes.Alert)
{
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="() => CloseModal()">
<span aria-hidden="true">×</span>
</button>
}
else if (DT == DialogTypes.Prompt)
{
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="() => CloseModal(false)">
<span aria-hidden="true">
×
</span>
</button>
}
}
</div>
@{
if (DT == DialogTypes.Alert)
{
<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" data-dismiss="modal" @onclick="() => CloseModal()">Close</button>
}
else if (DT == DialogTypes.Prompt)
{
<button type="button" class="btn btn-primary" data-dismiss="modal" @onclick="() => CloseModal(true)">Yes</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" @onclick="() => CloseModal(false)">No</button>
}
}
</div>
</div>
</div>
和固定警报:
public Task<bool> PromptAsync(string title)
{
// Check if the modal is already running and exit if it is
if (!_alertTask.IsCompleted || !_task.IsCompleted)
return Task.FromResult(false);
DT = DialogTypes.Prompt;
Title = title;
ModalDisplay = "block;";
ModalClass = "show";
StateHasChanged();
_alertTaskCompletionSource = new();
_alertTask = _alertTaskCompletionSource.Task;
return _alertTask;
}
评论
1赞
MrC aka Shaun Curtis
6/14/2023
请随时修改我的答案和您的更正。这意味着有一个公认的答案。
评论