Reputation: 14860
I'm currently implementing a MessageDialog control. It is there to replace MessageBox
entirely and is displayed as an "in-window popup" (correct UX term needed).
Currently, its constructor is private and there is a method Show
, just like in MessageBox.Show
. However, MessageBox
blocks the UI thread and returns a result.
What my MessageDialog
control currently does is having a Action<MessageDialogResult> callback
parameter which gets called when a button is clicked.
Utilizing MessageDialog
// class MessageDialog
public static void MessageDialog.Confirmation(Window owner, string message, Action<MessageDialogResult> callback);
// When used by other controls
MessageDialog.Confirmation(WindowMain.Singleton, true, (result) =>
{
if (result.Button == MessageDialogButton.Yes)
{
//...
}
});
However, having a callback instead of a blocking method call like in MessageBox.Show
yields absolutely no benefits for me. It makes things rather complicated. What I'm rather trying to achieve is something like...
if (MessageDialog.Confirmation(WindowMain.Singleton, true).Button == MessageDialogButton.Yes)
{
//...
}
... which is much cleaner in my opinion.
The current code behind is basically
MessageDialog
and populate content with textWindow.Content.Children
callback(result)
and remove from Window.Content.Children
The question: What I would like to achieve is having a blocking method call instead of one that triggers a callback.
Upvotes: 0
Views: 1114
Reputation: 503
Even though the accepted answer seems to work, I propose a better solution using TaskCompletionSource
. This is exactly what await
was made for - it's still basically just a callback (won't block the thread), but your code looks a lot simpler when using it.
TaskCompletionSource<DialogResult> taskSource;
Task<DialogResult> ShowAsync()
{
return taskSource.Task;
}
public void OkButton_OnClick(EventArgs e, object sender)
{
taskSource.SetResult(DialogResult.OK);
}
public void CancelButton_OnClick(EventArgs e, object sender)
{
taskSource.SetResult(DialogResult.Cancel);
}
You then have to await the call: await Dialog.ShowAsync()
Upvotes: 3
Reputation: 52290
How about something like this:
//DialogControl.cs
bool _closed = false;
DialogResult _result;
DialogResult ShowModal()
{
this.Show();
while(!_closed) Application.DoEvents(); //Infinite loop
return _result;
}
public void OkButton_OnClick(EventArgs e, object sender)
{
_result = DialogResult.OK;
_closed = true;
}
public void CancelButton_OnClick(EventArgs e, object sender)
{
_result = DialogResult.Cancel;
_closed = true;
}
Upvotes: 1