Windows Azure Cloud Storage ermöglicht es Ihnen bereits ab 0,10€ pro GB/Monat die Vorteile der Cloud zu nutzen.
Willkommen bei dotnet-snippets.de! Snippet hinzufügen Login Registrieren
Snippets in der Datenbank: 1551 | Anzahl registrierter User: 1841 | Besucher online: 124
Hauptmenü
Home
Top Ten
Zufälliger Snippet
FAQs
.NET Community
dotnet-forum.de
dotnet-kicks.de
Social

RSS Feeds
Rss Alle Snippets
Rss C#
Rss VB.NET
Rss C++
Rss ASP.NET
Partner
Member of Microsoft Community Leader/Insider Program (CLIP)

Asynchrones nachladen von Bildern in DataGridView


Autor: Rüdiger Vossel
Sprache: C#
Bewertung:
noch nicht bewertet
Anzahl der Aufrufe: 8208
  
Kick it on dotnet-kicks.de  

Beschreibung:

Bei einem DataGridView hat man die Möglichkeit eine (oder mehrere) Spalten als Image-Spalte zu definieren.

In dieser Spalte hat man die Möglichkeit Bilder in eine Tabelle zu integrieren. Wenn diese Bilder aber von externer Quelle, sei es ein FileServer oder ein Webservice geladen werden müssen, entstehen unschöne Wartezeiten beim Aufbau des Grids. Vor allem wenn große Datenmengen angezeigt werden sollen ist das Laden der Bilder beim füllen des Grids nicht tragbar.

Das folgende Snippet ist als Anregung gedacht, wie man solche Bilder (am Besten Thumbs der Originalbilder) asynchron, bei Bedarf nachladen kann.



Um die Beispielklasse (ja es ist eine ganze Klasse J) zu kompilieren brauchen wir ein Projekt mit einer Windows-Form (Form1) und einem ungebundenen DataGridView (dataGridView1). Beim DataGridView sollte Hinzufügen, Bearbeiten und Löschen (im ersten Schritt) nicht aktiviert sein.


Abgelegt unter: asynchron, Thread, marshalling, DataGridView, threadsicher.



C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace SnippetASLoader
{
    public partial class Form1 : Form
    {
        delegate void BildEintragenCallback(List<object> parameter);
        private List<String> dateinamen;

        public Form1()
        {
            //Infos zu den Einstellungen der visuellen Komponenten:
            //Das Grid (dataGridView1) is gedockt (Dock=fill);
            //Hinzufügen, Löschen, Bearbeiten .. alles aus!
            //Zwei Spalten:
            //  Column1 -> DataGridViewImageColumn
            //  Column2 -> DataGridViewTextBoxColumn
            InitializeComponent();
            //Sachen die wir für's Beispiel brauchen...
            this.dateinamen = new List<string>();
            dateinamen.Add(@"c:\temp\Bild01.png"); //Ja geht auch anders :-)
            dateinamen.Add(@"c:\temp\Bild02.png");
            dateinamen.Add(@"c:\temp\Bild03.png");
            dateinamen.Add(@"c:\temp\Bild04.png");
            dateinamen.Add(@"c:\temp\Bild05.png");
            dateinamen.Add(@"c:\temp\Bild06.png");
            dateinamen.Add(@"c:\temp\Bild07.png");
            dateinamen.Add(@"c:\temp\Bild08.png");
            dateinamen.Add(@"c:\temp\Bild09.png");
            dateinamen.Add(@"c:\temp\Bild10.png");
        }

        /// <summary>
        /// Standard Load-methode des Fensters ... 
        /// Hier füllen wir das Grid initial...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.SuspendLayout();
            dataGridView1.Rows.Clear(); //Paranoider Sicherheitsabstand ... nicht wirklich nötig
            //Eintragen der nicht Bild-Daten ins Grid
            int z = -1;
            foreach (String zeile in dateinamen)
            {
                z++;
                dataGridView1.Rows.Add(); //Neue Zeile
                dataGridView1.Rows[z].Height = 128; //An Bildergröße anpassen!
                dataGridView1.Rows[z].Tag = zeile; //Hier den Pfad zum Bild ablegen!
                //SnippetASLoader.Properties.Resources.BildWirdGeladenBild -> "Standard-Bild" aus Resource
                dataGridView1.Rows[z].Cells[0].Value = SnippetASLoader.Properties.Resources.BildWirdGeladenBild;
                //Anhand dieser "null" merken wir uns, ob das Bild bereits nachgeladen wurde..
                dataGridView1.Rows[z].Cells[0].Tag = null;
                //Der Rest ... also alle Daten die wir haben!
                dataGridView1.Rows[z].Cells[1].Value = zeile;
            }
            dataGridView1.ResumeLayout();
        }

        /// <summary>
        /// Bevor die Zeile "gemalt" wird!!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
            if (row.Cells[0].Tag == null) //Wir erinnern uns an den Merker vom Form1_Load? *G*
            {
                row.Cells[0].Tag = true; //Ab jetzt nicht mehr nachladen! (Nachladen läuft....)
                //Vorbereiten zum Starten eines neuen Threads
                List<Object> paramter = new List<object>();
                paramter.Add(row.Index);
                paramter.Add(row.Tag);
                ParameterizedThreadStart pts = new ParameterizedThreadStart(this.bildLaden);
                Thread serverThread = new Thread(pts);
                //Und Thread starten...
                serverThread.Start(paramter);
            }
        }

        /// <summary>
        /// Methode die in einem eigenen Thread läuft...
        /// </summary>
        /// <param name="o"></param>
        private void bildLaden(Object o)
        {
            List<Object> parameter = (List<Object>)o;
            int rowIndex = (int)parameter[0];
            string pfadZumBild = (string)parameter[1];

            //Thumb
            Image i;
            FileInfo fi = new FileInfo(pfadZumBild);
            if (fi.Exists)
            {
                i = Image.FromFile(fi.FullName); //Oder aus Stream oder sonst wie ...
            }
            else
            {
                i = SnippetASLoader.Properties.Resources.BildNichtGefundenBild;
            }
            List<object> result = new List<object>();
            result.Add(rowIndex);
            result.Add(i);

            //Zurückgeben des Ergebnisses
            this.bildEintragen(result);
        }

        /// <summary>
        /// Trägt das Ergebnis des Threads sicher in das Steuerelement ein.
        /// </summary>
        /// <param name="parameter"></param>
        private void bildEintragen(List<object> parameter)
        {
            if (this.dataGridView1.InvokeRequired)
            {
                //Delegaten Aufruf um das Steuerlement Thredsicher anzusprechen
                BildEintragenCallback tec = new BildEintragenCallback(bildEintragen);
                this.Invoke(tec, new object[] { parameter });
            }
            else
            {
                int rowIndex = (int)parameter[0];
                Image bild = (Image)parameter[1];
                dataGridView1.Rows[rowIndex].Cells[0].Value = bild;
            }
        }
    }
}
Sie haben Fragen zu diesem Snippet oder brauchen Hilfe bei der .NET Entwicklung?
Freundliche und kompetente Entwickler helfen Ihnen gern weiter im Forum für .NET Entwicklung.



Kommentare:
(Zum Schreiben von Kommentaren bitte anmelden.)



schlecht sehr gut
1 2 3 4 5 6 7 8 9 10
Nur angemeldete User können Snippets bewerten.