• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

nero_lux

Alteração do conteudo de uma label

10 mensagens neste tópico

Bom dia, estou com uma dúvida mesmo básica. Não consigo alterar dinamicamente o conteudo da minha Label.

Passo a explicar, no meu ecrã de inicialização da aplicação vou efectuar várias verificações do tipo, se o ficheiro de configuração da aplicação existe, se a base de dados existe... A medida que vou efectuar essas verificações prentendo alterar o Content da minha Label, informando o Utilizador da tarefa que está a ser executada.

Assim não funciona:


private void SbCompleted(object sender, EventArgs e)
{

       LblMsg.Content =  "Inicializar os componentes..";
       DoEvents();
       Thread.Sleep(1000);
       LerConfiguracoes();
       WindowLogin FrmLogin = new WindowLogin();
       FrmLogin.Show();

} //SbCompleted

A única solução que encontrei foi associar um MouseDoubleClick à Label e assim já funciona:


private void LblMsg_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{

    LblMsg.Content =  "Inicializar os componentes..";
    DoEvents();
   Thread.Sleep(1000);
   LerConfiguracoes();
   WindowLogin FrmLogin = new WindowLogin();
   FrmLogin.Show();
		// TODO: Add event handler implementation here.
}

O que estou a fazer de errado?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Que queres dizer com não funciona?

A label não é actualizada, ou está a lançar uma excepção?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas,

Isso acontece porque o conteúdo dos controlos é alterado de forma assíncrona, através de mensagens processadas pelo Dispatcher do WPF quando a thread está *livre*, e o facto é que a sua thread não está livre... Muito pelo contrário, está a "dormir" por alguns segundos.

Isso significa que os controlos somente serão actualizados quando este bloco de código terminar a execução.

O *correcto* para fazer o que você pretende é criar uma segunda thread para ler as configurações, deixando a thread principal livre, e somente quando esta segunda thread terminar, é que você abre o formulário de Login.

A forma mais simples de fazer isso é utilizando o controlo BackgroundWorker, que se encarrega de executar o seu código em uma thread separada, e avisa quando a execução terminou... Tudo através de eventos.

Uma outra alternativa, seguindo a sua linha de pensamento no código que mostrou, seria invocar o Dispatcher explicitamente, para forçar a actualização do controlo antes da Thread "dormir"... Algo como:

LblMsg.Content =  "Inicializar os componentes..";

// Sinaliza que o label deve ser redesenhado
LblMsg.UpdateLayout();

// Solicita ao Dispatcher que execute as acções pendentes no LblMsg
LblMsg.Dispatcher.Invoke(new Action(() => { }), 
    System.Windows.Threading.DispatcherPriority.Background);

Vale lembrar que essa *não* é propriamente uma boa prática, mas é similar ao DoEvents que você estava a tentar executar.

Cumprimentos,

Caio Proiete

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E pq dizes q a tua segunda solução não é uma boa prática?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E pq dizes q a tua segunda solução não é uma boa prática?

Boas,

Porque a aplicação continua "congelada" na mesma, e o utilizador não pode interagir com a aplicação enquanto o bloco de código estiver a ser executado. A única diferença é que agora o texto do Label aparece...

Em termos de experiência de utilizador, é como se ainda estivéssemos em 1998  ;)

Cumprimentos,

Caio Proiete

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A utilização do BeginInvoke em vez do Invoke seria uma solução?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A utilização do BeginInvoke em vez do Invoke seria uma solução?

Também não... O BeginInvoke não cria uma nova thread... Ele apenas coloca o delegate na fila do Dispatcher, para ser executado de forma assíncrona, mas ainda acontece na thread principal (que está ocupada/a dormir).

A solução *correcta*, como eu disse abaixo, é criar uma nova thread para executar o processamento, e deixar a thread da interface gráfica livre para que o utilizador possa interagir.

Cumprimentos,

Caio Proiete

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas,

mas diz-me uma coisa sempre que pretendo alterar o conteudo da minha Label tinha que criar um  Dispatcher?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas,

mas diz-me uma coisa sempre que pretendo alterar o conteudo da minha Label tinha que criar um  Dispatcher?

Não. O Dispatcher é para quando uma thread está a tentar modificar recursos (neste caso o conteúdo da label) da thread principal. Se for na thread que é dona do recurso não precisas de usar o Dispatcher.
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boa Noite, obrigado pela vossa ajuda, resolvi o meu problema usando o BackgroundWorker.

Muito Obrigado!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora