OneWileyDog
OneWileyDog

Reputation: 37

C# WPF Trying to put up a Please Wait dialog

In my main window, I have a button that generates a report. But the report takes about 15 seconds to build, so I simply want to put up a small dialog that asks the user to "Please wait". It then just goes away when the report window is activated. The below works except that the "Please wait" dialog only produces the shell of the window, no content. Here is the code:

WD_PleaseWaitDialog _pWait = null;
private void ReportButton_Click( object sender, RoutedEventArgs e )
{
 _pWait = new WD_PleaseWaitDialog();
 _pWait.Show();

 ReportWindow reportWindow = new ReportWindow(); // takes 15 seconds to execute
 reportWindow.Activated += closePleaseWaitWindow;
 reportWindow.Show();
} 
private void closePleaseWaitWindow( object sender, System.EventArgs e )
{
_pWait.Close();
}

Upvotes: 0

Views: 1277

Answers (3)

OneWileyDog
OneWileyDog

Reputation: 37

Thank you all for your answers. This is a great site and has provided me with lots of good info. This is what works, but it does not seem as elegant as I would like it to be:

private void ReportButton_Click( object sender, RoutedEventArgs e )
{
  reportWindow = new BackUp.ReportWindow();
  StatusBarTextBox.Text = "Generating report for \"" + DestinationDirectoryTextBox.Text + "\"";
  StartWork();
} // END ReportButton_Click 

private void StartWork()
{ 
  _pWait = new WD_PleaseWaitDialog();
  _pWait.Show();

  BackgroundWorker worker = new BackgroundWorker();
  worker.DoWork += DoWork;
  worker.RunWorkerCompleted += WorkerCompleted;
  worker.RunWorkerAsync();
}

private void DoWork( object sender, DoWorkEventArgs e )
{
   reportWindow.initializeReportWindow( _dailyList, _weeklyList, _monthlyList, _semiAnnualList );  
}

private void WorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
{
   _pWait.Close();
   reportWindow.Show();          
} 

With this approach, I had to move the ReportWindow initialization out of the constructor and move it to an accessor.

Upvotes: 1

B.K.
B.K.

Reputation: 10152

What's happening is that your WD_PleaseWaitDialog gets instantiated and when you Show() it, it goes into Loaded state, but that's right before Rendered lifetime state. This is when you are creating your ReportWindow, which takes a while to process (15 seconds according to you). What's happening is that you're essentially blocking the main thread during that time, which prevents WD_PleaseWaitDialog from completing its rendering phase of its lifetime cycle. By the time your ReportWindow finishes its loading, both of them get rendered, but it's so quick that you may not see the content of the WD_PleaseWaitDialog at all before it's closed.

There are a couple of things you can do...

  • You might try working with the ContentRendered event of the WD_PleaseWaitDialog in order to proceed with the rest of the code. But, that couples the two windows... and that's not something I personally prefer.

  • You may consider using different threads. Task class can greatly help you in this. One way this may be done is to put lengthy operations in your ReportWindow into a Task:

    Task.Run(() => { // lengthy operation here });

When you're done with the operation, you'll need to call back into the main thread to close your WD_PleaseWaitDialog (since you can't handle UI operations in other threads):

Application.Current.Dispatcher.BeginInvoke(
    Dispatcher.Normal, new Action(_pWait.Close));

I'm not going to provide you the whole code unless you get really stuck. Try to do it yourself, since I've given you plenty of information to get started. Hope that helps.

Upvotes: 0

Liero
Liero

Reputation: 27348

Use dispatcher.begininvoke to generate and show report

Dispatcher.BeginInvoke(new Action(()=>{ /* report window */ });

Upvotes: 0

Related Questions