Janela de progresso modal do WPF
Peço desculpas se esta pergunta foi respondida muitas vezes, mas não consigo encontrar uma resposta que funcione para mim. Eu gostaria de criar uma janela modal que mostra várias mensagens de progresso enquanto meu aplicativo executa tarefas de execução longa. Essas tarefas são executadas em um thread separado e eu posso atualizar o texto na janela de progresso em diferentes estágios do processo. A comunicação cross-thread está funcionando bem. O problema é que não consigo fazer com que a janela fique apenas em cima de outras janelas de aplicativos (nem de todos os aplicativos no computador), permaneça no topo, evite a interação com a janela pai e ainda permita que o trabalho continue.
Aqui está o que eu tentei até agora:
Primeiro, minha janela inicial é uma classe personalizada que estende a classe Window e tem métodos para atualizar a caixa de mensagem. Eu crio uma nova instância da classe splash no início e mostro / oculto conforme necessário.
No mais simples dos casos, eu instancio a janela e chamo.Show()
nele:
//from inside my secondary thread
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Show());
//Do things
//update splash text
//Do more things
//close the splash when done
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Hide());
Isso exibe corretamente a janela e continua executando meu código para manipular as tarefas de inicialização, mas permite que eu clique na janela pai e traga isso para a frente.
Em seguida, tentei desativar a janela principal e reativar mais tarde:
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = false));
//show splash, do things, etc
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = true));
Isso desativa todos os elementos da janela, mas ainda posso clicar na janela principal e trazê-la para a frente da tela inicial, que não é o que eu quero.
Em seguida, tentei usar a propriedade mais alta na janela inicial. Isso o mantém na frente de tudo, e em conjunto com a configuração da propriedade IsEnabled da janela principal eu poderia impedir a interação, mas isso faz com que a tela inicial apareça na frente de TUDO, incluindo outros aplicativos. Eu também não quero isso. Eu só quero que seja a janela mais alta dentro desta aplicação.
Então eu encontrei posts sobre o uso.ShowDialog()
ao invés de.Show()
. Eu tentei isso, e ele mostrou corretamente o diálogo e não me permitiu clicar na janela pai, mas chamando.ShowDialog()
faz com que o programa fique aguardando que você feche a caixa de diálogo antes de continuar executando o código. Isto é obviamente, não o que eu quero também. Eu suponho que eu poderia ligarShowDialog()
em um segmento diferente para que esse segmento iria travar, mas o segmento fazendo o trabalho não seria ... é o método recomendado?
Também considerei a possibilidade de não usar uma janela e, em vez disso, colocar um elemento de janela em tamanho real na frente de todo o resto da página. Isso funcionaria, exceto que eu tenho outras janelas abertas e gostaria de poder usar a tela inicial quando elas estiverem abertas também. Se eu usasse um elemento de janela, teria que recriá-lo em todas as janelas e não conseguiria usar o meu práticoUpdateSplashText
método na minha classe splash personalizada.
Então isso me leva à questão. Qual é o caminho certo para lidar com isso?
Obrigado pelo seu tempo e desculpe pela longa pergunta, mas os detalhes são importantes :)