Question

webdeveloper net et généralement ne font pas des applications win32. mais maintenant je dois. J'ai une liste avec environ 2000 entrées. chaque entrée doit être affichée comme une étiquette avec une autre étiquette et zone de texte image. j'ai fait cela avec un FlowLayoutPanel et je l'ai fait une foreach sur les entrées pour faire un panneau pour chaque entrée avec l'étiquette, zone de texte, l'étiquette et un picturebox.

maintenant je l'ai rendu des questions en ce qui concerne plus de 1000 entrées. donc j'ai lu que je devrais utiliser un listview ou datagridview.

J'ai maintenant datagridview comme ceci:

DataGridView dgv = new DataGridView();
dgv.AutoSize = true;
dgv.ScrollBars = ScrollBars.Vertical;

System.Data.DataTable dt = new System.Data.DataTable();
DataColumn dc1 = new DataColumn("Code", typeof(string));
dc1.ReadOnly = true;
dt.Columns.Add(dc1);
dt.Columns.Add(new DataColumn("Quantity", typeof(int)));
DataColumn dc3 = new DataColumn("Price", typeof(string));
dc3.ReadOnly = true;
dt.Columns.Add(dc3);
dt.Columns.Add(new DataColumn("Image", typeof(Bitmap)));

foreach (Product pd in products)
{
      DataRow dr = dt.NewRow();
      dr["Code"] = pd.ProductCode;
      dr["Quantity"] = pd.ProductQuantity;
      dr["Price"] = "€ " + String.Format("{0:0,00}", pd.ProductResalePrice.ToString());

      dr["Image"] = BitmapFromWeb(pd.ProductImage);
      dt.Rows.Add(dr);
}

dt.AcceptChanges();
dgv.RowTemplate.Height = 50;
dgv.DataSource = dt;

mais la chose est qu'un bitmap sur un datagridview est vraiment lent! l'option picturebox et les panneaux que j'avais avant où beaucoup plus rapide. Comment puis-je résoudre ce problème?

la deuxième question est: quel événement ai-je besoin quand je veux suivre les modifications apportées dans la 2ème colonne

OW une chose: les images sont disponibles en ligne de sorte que le 'pd.ProductImage' est une url

    private static Bitmap BitmapFromWeb(string URL)
    {
        try
        {
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(URL);
            myRequest.Method = "GET";
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
            myResponse.Close();

            return bmp;
        }
        catch (Exception ex)
        {
            return null; // if for some reason we couldn't get to image, we return null
        }
    }
Était-ce utile?

La solution

Faites la charge d'image asyncrhonously forcer alors un rafraîchissement de la cellule. Vous pouvez mettre votre code foreach dans un appel à la ThreadPool, quelque chose comme ...

ThreadPool.QueueUserWorkItem(delegate
{
 foreach (DataRow row in dt)
 {
  row["Image"] = BitmapFromWeb(Products[row["Code"]].ProductImage);
  //maybe a call to invalidate here, remember to do Control.Invoke(...)
 }
}

Edit: voici un exemple de code que je l'ai testé dans le constructeur du formulaire ...

        DataTable t= new DataTable();
        t.Columns.Add("id");
        t.Columns.Add("uri");
        t.Columns.Add(new DataColumn("Img",typeof(Bitmap)));

        Bitmap b = new Bitmap(50, 15);
        using (Graphics g = Graphics.FromImage(b))
        {
            g.DrawString("Loading...", this.Font, new SolidBrush(Color.Black), 0f,0f);
        }

        t.Rows.Add(new object[] { "1", "http://farm1.static.flickr.com/88/377522544_c4774f15cc_s.jpg", b });
        t.Rows.Add(new object[] { "2", "http://farm1.static.flickr.com/175/377522405_2c505def99_s.jpg", b });
        t.Rows.Add(new object[] { "3", "http://farm1.static.flickr.com/185/377524902_72f82e2db9_s.jpg", b });
        t.Rows.Add(new object[] { "4", "http://farm1.static.flickr.com/136/377524944_d011abf786_s.jpg", b });
        t.Rows.Add(new object[] { "5", "http://farm1.static.flickr.com/137/377528675_d3b9d541fb_s.jpg", b });
        dataGridView1.DataSource = t;
        ThreadPool.QueueUserWorkItem(delegate
        {
            foreach (DataRow row in t.Rows)
            {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(row["uri"].ToString());
                myRequest.Method = "GET";
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
                myResponse.Close();

                row["Img"] = bmp;
            }
        });

        dataGridView1.CellEndEdit += dataGridView1_CellEndEdit;

.... et dans le code d'édition de fin de cellule:

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        string value = dataGridView1.Rows[e.RowIndex].Cells["uri"].Value.ToString();
        ThreadPool.QueueUserWorkItem(delegate
        {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(value);
                myRequest.Method = "GET";
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
                myResponse.Close();
                dataGridView1.Rows[e.RowIndex].Cells["Img"].Value=bmp;
        });
    }

Autres conseils

// table is DataTable object declared as member in my form class
table = new DataTable();
table.Columns.Add(new DataColumn("Column1", typeof(string)));
table.Columns.Add(new DataColumn("Column2", typeof(string)));
table.Columns.Add(new DataColumn("Column3", typeof(System.Drawing.Bitmap)));

dataGridView1.DataSource = table;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top