2010-06-15 3 views
2

Dans un Windows Form, j'ai un champ de recherche qui déclenche un événement pour rechercher une base de données distante et afficher des résultats. La requête est assez rapide, généralement juste une fraction de seconde, mais dans le cas où le retard est perceptible, il y a une barre de progression et une étiquette dans la barre d'état du formulaire. Lorsque l'utilisateur clique sur "Rechercher", l'étiquette d'état devrait apparaître et la barre de progression montre quelques progrès. Ensuite, lorsque le résultat revient, l'étiquette devrait disparaître et la barre de progression devrait être pleine. Réponse assez basique.Mise à jour de ToolStripProgressBar et ToolStripStatusLabel avec une action

Le problème est que je n'arrive pas à obtenir ces actions dans cet ordre. En utilisant le code ci-dessous, je clique sur "Rechercher", rien ne se passe jusqu'à ce que les résultats soient affichés, puis la barre de progression se remplit de 0 à 100. L'étiquette n'apparaît jamais. J'ai même lancé une commande de sommeil immédiatement après l'événement pour être sûr que je ne l'ai pas manquée, mais c'est comme si les deux premières instructions n'étaient pas exécutées. Qu'est-ce que je fais mal ici?

private void searchButton_Click(object sender, EventArgs e) 
    { 
     toolStripStatusLabel1.Visible = true; 
     toolStripProgressBar1.Value = 20; 
     m_changeRequestedEvents.Fire<String>("SearchTerm", searchTextBox.Text); 
     toolStripProgressBar1.Value = 100; 
     toolStripStatusLabel1.Visible = false; 
    } 
+0

Cette méthode Fire lance-t-elle un autre thread pour effectuer la requête de la base de données? Si non, la raison pour laquelle vous ne voyez jamais l'étiquette est que vous faites tout sur le même fil. Dans Windows Forms, le thread principal est seul responsable de la peinture des fenêtres et du contenu. S'il est accroché en train d'effectuer des tâches ADO.NET, il ne peut pas très bien contourner l'étiquette. Au moment où il reviendra aux événements de mise en page/peinture des contrôles de service, il aura déjà fait la requête et la rendra invisible. –

+0

Non, il s'agit d'une application monothread. L'événement exécute une requête de base de données d'une autre classe, qui déclenche ensuite un autre événement vers l'interface utilisateur pour mettre à jour une table de résultats. Je comprends qu'il ne peut pas repeindre pendant l'exécution de la requête, mais étant donné le code ci-dessus, je pense qu'il remplirait partiellement la barre et afficherait l'étiquette * avant * de faire le backend, puis exécuterait les 2 dernières lignes une fois fini. –

+2

L'interface utilisateur ne se met pas à jour tant que searchButton_Click() n'est pas terminé. Vous devez exécuter la requête sur un autre thread. Regardez dans BackgroundWorker. –

Répondre

1

Le code fourni modifie les attributs interface utilisateur, mais le fil ne peut pas repeindre l'interface utilisateur qu'après retour searchButton_Click. Ainsi, les modifications apportées avant l'événement ne sont jamais appliquées, car elles sont remplacées par les modifications apportées après, qui sont ensuite appliquées lors du retour de la méthode.

Au lieu de cela, mettre à jour l'interface utilisateur attribue avant de déclencher l'événement:

searchButton.Enabled = false; 
toolStripProgressBar1.Value = 0; 
toolStripStatusLabel1.Visible = true; 
m_changeRequestedEvents.Fire<String>("SearchTerm", searchTextBox.Text); 

et à partir du gestionnaire d'événements, exécuter la requête dans un fil séparé (BackgroundWorker), de sorte que l'interface utilisateur peut mettre à jour dans l'intervalle:

private void View_OnSearchTermChangeRequest(Object sender, PropertyChangeRequestEventArgs<String> args) 
{ 
    m_search_bgw = new BackgroundWorker(); 
    ... 
    m_DBHandler.current_worker = m_search_bgw; 
    m_search_bgw.RunWorkerAsync(args.RequestedValue); 
} 

puis mettre à jour l'interface utilisateur à nouveau dans la méthode qui est appelée lorsque le fil BackgroundWorker complète:

void UpdateView(DataView projects) 
{ 
    dataGridView1.DataSource = projects; 
    ... 
    toolStripProgressBar1.Value = 100; 
    toolStripStatusLabel1.Visible = false; 
} 
Questions connexes