Progressbar pour le chargement des données dans DataGridView en utilisant DataTable

j'ai un DataGridView dans lequel je charge des données à partir d'une base de données SQL server. Quand je charge les données, cela prend beaucoup de temps.

je voudrais donner à l'Utilisateur des informations que les données sont en train de charger. Puis-je vous demander Quelle est la meilleure façon de se connecter?--2-- > quand data charge dans le DataGridView?

Je ne veux pas que quelqu'un fasse un code entièrement fonctionnel pour moi. J'aimerais juste savoir comment il peut être fait.

je vois quelqu'un qui a reçu ma question avec une prime. Je voudrais pour dire qu'en ce moment je suis en utilisant ce code que j'apprécierais s'il convenait.

DTGdataTable = new DataTable();
SqlDataAdapter SDA = new SqlDataAdapter
SDA.Fill(DTGdataTable);
dataGridView1.DataSource = DTGdataTable ;

merci à tous pour votre temps.

14
demandé sur Marek 2013-08-22 14:23:18

5 réponses

Si le problème est que cela prend du temps pour récupérer les données depuis la base de données, j'ai une solution pour vous:

    private void buttonLoad_Click(object sender, EventArgs e)
    {
        progressBar.Visible = true;
        progressBar.Style = ProgressBarStyle.Marquee;
        System.Threading.Thread thread = 
          new System.Threading.Thread(new System.Threading.ThreadStart(loadTable));
        thread.Start();
    }

    private void loadTable()
    {
        // Load your Table...
        DataTable table = new DataTable();
        SqlDataAdapter SDA = new SqlDataAdapter();
        SDA.Fill(table);
        setDataSource(table);
    }

    internal delegate void SetDataSourceDelegate(DataTable table);
    private void setDataSource(DataTable table)
    {
        // Invoke method if required:
        if (this.InvokeRequired)
        {
            this.Invoke(new SetDataSourceDelegate(setDataSource), table);
        }
        else
        {
            dataGridView.DataSource = table;
            progressBar.Visible = false;
        }
    }

mettez la méthode chargeant les données dans un autre thread et définissez la source de données quand elle est terminée. Il devrait y avoir une invoquer nécessaire. Si vous voulez afficher des valeurs en pourcentage dans la barre de progression, n'utilisez pas le style 'Marquee' et ajoutez une autre fonction et delegate que vous pouvez invoquer pour définir la valeur de la barre de progression.

si liant les données la grille est le problème, alors vous ne pouvez pas mettre la liaison dans un autre thread et vous pouvez montrer un progrès-popup qui s'exécute dans un autre thread.

j'espère que cette aide.

18
répondu Michael 2014-01-28 07:39:34

Essayez ceci...Ce doit être la voie la plus rapide...

1) Add a button control.
2) Add a datagridview control.
3) Add a single column into the datagridview control.
4) Add a progressbar control.
5) Leave them all with default names.

sous l'événement button1_Click, ajoutez ce morceau de code...

int maxnumber = 1000;
progressBar1.Value = 0;
progressBar1.Maximum = maxnumber;
for (int x = 0; x <= maxnumber - 1; x++)
{
    Application.DoEvents();
    dataGridView1.Rows.Add(new string[] {Convert.ToString(x)});
    progressBar1.Value += 1;
    label1.Text = progressBar1.Value.ToString();
}

c'est tout. Modifier pour l'adapter à vos besoins. Ce n'est pas le code exact que vous voulez, mais ça devrait vous aider à démarrer. J'ai pris la liberté de déclarer maxnumber pour maintenir la limite de la barre de progression. Dans votre cas, ce devrait être le nombre de lignes de votre base de données et il est soustrait par 1 puisque l'index commence toujours par zéro :)

la méthode ci-dessus est filetée simple, ce qui signifie que vous ne pouvez toujours pas faire multitâche tant que votre boucle n'est pas encore terminée. Dans certains cas, en fonction de l'algorithme du code, l'utilisation de la méthode filetée simple peut être plus rapide que d'aller pour la route multi-lecture. Quoi qu'il en soit, la deuxième méthode serait d'utiliser un travailleur de fond. Ceci est le plus souvent préféré par les gens puisque l'utilisateur peut encore faire des choses pendant que la liste charge. Un peu comme des installateurs où vous pouvez annuler l'installation même si c'est en train de faire quelque chose. Le site Web ci-dessous devrait vous aider à démarrer. Le code est dans VB.NET mais peut être facilement converti en C# :)

http://social.msdn.microsoft.com/Forums/vstudio/en-US/efd7510c-43ed-47c4-86a3-1fa350eb0d30/fill-datagridview-using-backgroundworker-progressbar?forum=vbgeneral

3
répondu chris_techno25 2014-01-28 00:32:43

le problème est que toutes les données se chargent ensemble et reviennent de la base de données. Vous devez obtenir la progression de chargement des données. Cela peut être fait à partir de la base de données.

  1. Obtenir le nombre de lignes de données à partir de la base de données. (Cette requête retournerait un seul numéro, donc ce serait plus rapide).

  2. Get the data in parts (Divide & conquer strategy), vous pouvez utiliser OFFSET et FETCH des requêtes de base de données. (C'est retourner une partie des données sur chaque appel) OFFSET et FETCH est disponible sur une base de données différente. En MSSQL, il a été introduit dans la version 2012.

Quand nous obtenons les données provenant du serveur, nous pouvons calculer le progrès.

2
répondu Haseeb Mukhtar 2014-01-28 18:24:42

dans votre code, cette ligne prendra la plupart du temps de traitement:

SDA.Fill(DTGdataTable);

donc, je pense que la chose la plus importante est de garder le suivi des progrès pendant que ce est l'exécution. Pour ce faire, vous devez d'abord savoir combien de lignes vous vous attendez. Le SQLDataAdapter ne peut pas fournir cette information, vous devrez donc lancer une requête supplémentaire (*) pour obtenir ce numéro. Vous pouvez alors l'utiliser comme le Maximum sur votre ProgressBar.

mon code de chargement réel est basé sur la solution de Michael Hofmeiers, mais au lieu d'utiliser la barre de progression en mode Marquee, Je l'alimenterais avec des données de progression réelles à partir d'un contrôle de minuterie. Ainsi, sur votre formulaire, vous ajoutez un contrôle de minuterie (appelé progressTimer dans mon exemple), réglez son intervalle à 100 msec et activé à false. Le code devient alors:

private DataTable table = null;

private void buttonLoad_Click(object sender, EventArgs e)
{
    // TODO: Select the row count here and assign it to progressBar.Maximum

    progressBar.Visible = true;             
    System.Threading.Thread thread = 
      new System.Threading.Thread(new System.Threading.ThreadStart(loadTable));
    thread.Start();
    progressTimer.Enabled = true;
}

private void loadTable()
{
    // Load your Table...
    this.table = new DataTable();
    SqlDataAdapter SDA = new SqlDataAdapter();
    SDA.Fill(table);
    setDataSource(table);
}

internal delegate void SetDataSourceDelegate(DataTable table);
private void setDataSource(DataTable table)
{
    // Invoke method if required:
    if (this.InvokeRequired)
    {
        this.Invoke(new SetDataSourceDelegate(setDataSource), table);
    }
    else
    {
        progressTimer.Enabled = false;
        dataGridView.DataSource = table;
        progressBar.Visible = false;
    }
}

private void progressTimer_Tick(object sender, EventArgs e)
{
    if (this.table != null)
        progressBar.Value = this.table.Rows.Count;
}

lorsque vous lancez ceci, votre application restera réactive pendant le chargement, et vous verrez la barre de progression changer pour refléter le nombre de lignes chargées. Seulement à l' end (lorsque vous définissez la source de données sur DataGridView) l'application semblera "hang", mais je ne pense pas qu'il y ait un moyen d'éviter cela. Vous ne pouvez faire cette opération qu'à partir du fil principal, il est donc inévitable que L'interface utilisateur ne réagisse pas. Mais dans mon test, le DataGridView gère facilement 300K + rows en une seconde, donc ça ne devrait pas être un gros problème.

2
répondu Jos Bosmans 2014-02-03 01:50:25

1.Télécharger un chargeur ajax.gif à partir de google.

2.remplacez cette image par ce code..

3.Régler l'heure en conséquence..

<div id="spinner" style="display: none;">
<span id="ss" style="float: left; margin-left: 50% !Important; margin-top: 22% !Important;">
<img src="ajax-pink-loader.gif" alt="Loading..." />
</span>
</div>

    $("#ssubmit").click(function () {
        $("#spinner").show();
        setInterval(function () {
            $("#spinner").hide();
        }, 20000);
    });
-4
répondu Sasidharan 2013-08-22 10:32:12