2015-02-28 7 views
0

В моем главном окне у меня есть кнопка, которая генерирует отчет. Но для создания требуется около 15 секунд, поэтому я просто хочу поставить небольшой диалог, который просит пользователя «Подождите». Затем он просто исчезает, когда активируется окно отчета. Нижеследующее работает, за исключением того, что в диалоговом окне «Подождите» создается оболочка окна, нет содержимого. Вот код:C# WPF Попытка установить диалоговое окно «Подождите»

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(); 
} 

ответ

0

То, что происходит в том, что ваш WD_PleaseWaitDialog получает экземпляр и когда вы Show() его, он переходит в состояние Loaded, но это прямо перед Rendered время жизни состояния. Это когда вы создаете свой ReportWindow, который требует времени для обработки (15 секунд в соответствии с вами). Что происходит, так это то, что вы в течение этого времени блокируете основной поток, что предотвращает завершение фазы рендеринга его цикла жизни WD_PleaseWaitDialog. К моменту, когда ваш ReportWindow закончит загрузку, оба из них получают визуализацию, но это так быстро, что вы можете не видеть содержимое WD_PleaseWaitDialog вообще до его закрытия.

Есть несколько вещей, которые вы можете сделать ...

  • Вы могли бы попробовать работать с ContentRendered событием WD_PleaseWaitDialog для того, чтобы приступить к остальной части кода. Но это соединяет два окна ... и это не то, что я лично предпочитаю.

  • Вы можете использовать различные темы. Task класс может очень помочь вам в этом. Один из способов это может быть сделано, чтобы положить длительные операции в вашем ReportWindow в Task:

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

Когда вы закончите с операцией, вам необходимо перезвонить в основной поток закрыть WD_PleaseWaitDialog (так как вы не можете выполнять операции пользовательского интерфейса в других потоках):

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

Я не собираюсь предоставить вам весь код, если вы не получите действительно застрял. Постарайтесь сделать это сами, так как я дал вам много информации, чтобы начать. Надеюсь, это поможет.

0

Использование dispatcher.begininvoke для создания и показать отчет

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

Это не решает проблему, так как все, что вы здесь делаете, вызывает основной поток из основного потока ... (что само по себе нечетно). Перенос 'WD_PleaseWaitDialog' будет по-прежнему блокироваться длительной операцией в' ReportWindow'. –

+0

Проблема в том, что waitdialog не отображается. Это решает проблему, потому что она начнет длительный процесс после рендеринга waitdialog. – Liero

+0

Нет, он не сказал, что диалог не отображается. Он сказал, что содержимое диалогового окна не отображается. Это совершенно разные вещи.Ваш код делает не что иное, как если бы он просто создал экземпляр диалогового окна и 'Show()' it, что он и сделал. Вы даже знаете, что делает 'Dispatcher.BeginInvoke()' делает? Это не так. –

0

Спасибо всем за ваши ответы. Это отличный сайт и предоставил мне много хорошей информации. Это то, что работает, но это, кажется, не так элегантно, как хотелось бы, чтобы это было:

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();   
} 

С таким подходом, я должен был переместить инициализацию ReportWindow из конструктора и переместить его в аксессору.

Смежные вопросы