I have a button in a panel, it will call another method which will create a user control to cover all over the panel. here is the code for the panel's button click event:
private void btnTarget_Click(object sender, EventArgs e)
{
UtilLoader.ShowLoader(this);
lblStatus.Text = "Done";
}
the code for ShowLoader is this:
internal class UtilLoader
{
public static void ShowLoader(Control parent)
{
var ct = new UcLoaderBox(parent)
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right,
Bounds = parent.ClientRectangle
};
parent.Controls.Add(ct);
ct.BringToFront();
ct.SubmitMessage += (sender, args) => { /* Here I can detect if user control is closed */ };
}
}
The user control has an event named SubmitMessage that will be fired if the user clicks on the button inside the user control. the btnTarget_Click will open up the user control and then immediately will execute lblStatus.Text = "Done;
I need to wait for SubmitMessage to be fired inside the user control.
I tried to do something like this using ManualResetEvent, but no success, it won't stop on await:
internal class UtilLoader
{
public static async void ShowLoader(Control parent)
{
var waiter = new ManualResetEvent(false);
var ct = new UcLoaderBox(parent)
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right,
Bounds = parent.ClientRectangle
};
parent.Controls.Add(ct);
ct.BringToFront();
ct.SubmitMessage += (sender, args) => { waiter.Reset(); };
await Task.Run(()=> waiter.WaitOne());
}
}
I also used below code and replacing await ct.WhenClicked instead of await Task.Run(()=> waiter.WaitOne()); in above code, but still no wait!
public static class Utils
{
public static Task WhenClicked(this Control target)
{
var tcs = new TaskCompletionSource<object>();
EventHandler onClick = null;
onClick = (sender, e) =>
{
((UcLoaderBox) target).SubmitMessage -= onClick;
tcs.TrySetResult(null);
};
((UcLoaderBox)target).SubmitMessage += onClick;
return tcs.Task;
}
}
What should I do to achieve my goal?
Updated:
With Andy's Answer, it will work fine now. But there is another problem.
That user control acts as a Modal and it will appear when it is needed. I'm adding and replacing it with the old message box system. the button may call a method that inserts into the database or another method that logs into a text file. inside these methods may the user control show as a modal on its parent control.
I can add the parent parameter into those methods and pass the parent control into them so whenever they want to show the modal, they can, and if not, nothing.
But converting all of these methods into async-await and converting all of the button events's into async-await is very hard.