I m using VS 2019 and Blazor Server Net5. The included bootstrap 4 environment offers modal dialogs and I would like to replicate something like the MessageBox() from good old Windows Forms. This means you execute (withhin a button click event) something like
DialogResult x = [await] MessageBox[Async]("SomeMsg", SomeButtons+SomeIcon);
And in x you would find what option the user did click (DialogResult.OK, Cancel, ...).
So I found several samples how to show the model dialog itself, and write it even as a component.
I have a simple component MessageBox.razor
public enum ModalResultType { Closed = 0, OK = 1, Cancel = 2, }
@if (ShowMessageBox == true)
{
<div class="modal fade show d-block" id="MessageBox" tabindex="-1"
role="dialog" aria-hidden="true">
.... and so forth ....
<button type="button" class="close" data-dismiss="modal" aria-label="Close"
@onclick="() => OnButtonClick(ModalResultType.Closed)">X</button>
... and so forth ...
<button type="button" class="btn btn-primary" data-dismiss="modal"
@onclick="() => OnButtonClick(ModalResultType.OK)">OK</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal"
@onclick="() => OnButtonClick(ModalResultType.Cancel)">Cancel</button>
.. and so forth ...
</div>
}
and in the cs behind file I can turn on the component show flag and display the component.
public async Task<ModalResultType> ShowAsync(string title, string messagetext)
{
Title = title;
Message = messagetext;
ShowMessageBox = true;
StateHasChanged();
//
// Now I m at a loss... how to await here what the User did click???
//
return whatTheUserDidClick;
}
// Click event from button, called with the appropiate ModalResultType
//
public async Task OnButtonClicked(ModalResultType value)
{
ShowMessageBox = false;
//
// Now I am at a loss - how to pass the clicked value into the waiting context
// of the UI above from and "complete" the awaiting ShowAsync();
//
}
The overall idea is to put into the framing App.Razor-Component this MessageBox component and so every "page" or other component has (via cascading parameter) access to the message box. And if it would need to create a modal MessageBox dialog, for example from some button click event, it could simply do so by calling
[CascadingParameter] public MessageBoxComponent AppRazorMessageComonent {get;set;}
public async Task SomeClickEvent()
{
// get some form data
// process them
// question arises ask user if to proceed or defer
if (await AppRazorMessageComponent.ShowAsync("Attention", "Shall we proceed?") == ModalResultType.OK)
{
// do stuff
}
else
{
// do other stuff
}
}
I found sample of modal dialogs where the event handler then is bound right to action to be carried out - like deleting a record. But this is not what I want - I would need to specifically bind the html always to the specifics of the page or component I m in at the time. Or I would need to supply a callback function, which would break my current track; like to set the ShowMessageBox flag, return from the click event, and then proceed along with the logic in another method.
So the question is: how can I await for an event withhin an event handler, which is triggered by an other UI event?
Do I need threads for this - I dont think so. It should be possible by Task, async and await only. But how to create an awaitable object, "signal" the completion, or cancellation, of such a Task? And in a way that it works withhin the Blazor UI component environment.