[vb.net] Grafische Progressbar in Datagridview-Zelle

Hallo zusammen.

Ich bin ein großer Freund des Datagridviews. Man kann Daten sehr einfach, übersichtlich und schön in einer Tabellenform darstellen. Doch manchmal möchte man dort auch gern eine Progressbar im Datagridview anzeigen lassen. Zum Beispiel wenn man sich einen Downloader bastelt und den aktuellen Stand des Downloads grafisch darstellen möchte. Oder auch wenn man statisch einen Prozentsatz grafisch darstellen möchte.

Leider gibt es standartmäßig keine Möglichkeit eine Progressbar in ein Datagridview einzubinden und das Element selbst unterstützt es auch nicht.

Nun führen bekanntlich viele Wege nach Rom. Manche sind lang und mühsam und manche sind recht simpel.
Ich habe auf meiner Suche Seitenlange Quelltexte gefunden, fertige DLL’s und schlussendlich eine sehr simple, aber effektive Möglichkeit. Die meine eigenen Überlegungen aufgegriffen hat. Nämlich die Progressbar einfach mit einem Bild zu imitieren. Das heißt es wird einfach ein Bild erstellt, welches dann in der entsprechenden Zelle eingebunden wird.
Dazu muss ich auch gleich sagen das diese Methode sehr Prozessorlastig werden kann, wenn viele „Progressbars“ im Datagrid existieren und diese oft geupdated werden. Wie viel mehr das im Vergleich zu den anderen Methoden ist, kann ich jedoch nicht sagen. Vielleicht macht es gar keinen großen Unterschied. Also entscheide selbst ob es für dein Programm geeignet ist.

Hier nun erst einmal der Code.

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim col As New ProgressColumn
        DataGridView1.Columns.Add(col)
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.RowCount = 5
        Dim x As Integer = 1
        For Each row As DataGridViewRow In DataGridView1.Rows
            row.Cells(0).Value = x * 20
            x += 1
        Next
    End Sub
End Class

Public Class ProgressColumn
    Inherits DataGridViewColumn
    Public Sub New()
        MyBase.New(New ProgressCell())
    End Sub

    Public Overrides Property CellTemplate() As DataGridViewCell
        Get
            Return MyBase.CellTemplate
        End Get
        Set(ByVal Value As DataGridViewCell)
            ' Ensure that the cell used for the template is a ProgressCell.
            If Value IsNot Nothing And Not TypeOf (Value) Is ProgressCell Then
                Throw New InvalidCastException("Must be a ProgressCell")
            End If
            MyBase.CellTemplate = Value
        End Set
    End Property
End Class

Public Class ProgressCell
    Inherits DataGridViewImageCell
    Protected Overrides Function GetFormattedValue(ByVal value As Object, ByVal rowIndex As Integer, ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal valueTypeConverter As System.ComponentModel.TypeConverter, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object
        ' Create bitmap.
        Dim bmp As Bitmap = New Bitmap(Me.Size.Width, Me.Size.Height)

        Using g As Graphics = Graphics.FromImage(bmp)

            ' Percentage.
            Dim percentage As Double = 0
            Double.TryParse(Me.Value.ToString(), percentage)
            Dim text As String = percentage.ToString() + " %"

            ' Get width and height of text.
            Dim f As Font = New Font("Verdana", 10, FontStyle.Regular)
            Dim w As Integer = CType(g.MeasureString(text, f).Width, Integer)
            Dim h As Integer = CType(g.MeasureString(text, f).Height, Integer)

            ' Draw pile.
            g.DrawRectangle(Pens.Black, 2, 2, Me.Size.Width - 6, Me.Size.Height - 6)
            g.FillRectangle(Brushes.Blue, 3, 3, CInt((Me.Size.Width - 6) * percentage / 100), CInt(Me.Size.Height - 7))

            Dim rect As RectangleF = New RectangleF(0, 0, bmp.Width, bmp.Height)
            Dim sf As StringFormat = New StringFormat()
            sf.Alignment = StringAlignment.Center
            g.DrawString(text, f, Brushes.Red, rect, sf)
        End Using

        Return bmp
    End Function


End Class

Was passiert hier nun?

Im Form_Load werden erst einmal die Datagridview-Spalten definiert und gefüllt. Dabei fällt auf das eine Zelle mit einem „ProgressColumn“ definiert wird. Das ist unsere Spezielle Progressbar-Zelle. Diese kann durch die folgende Klasse „ProgressColumn“ definiert werden.
Im Beispiel besteht unser Datagridview auch nur aus der einen Zelle (siehe auch Bild oben).

Dann wird das Datagridview-Element noch mit ein paar Testdaten gefüttert.

Die Klasse „ProgressColumn“ lässt uns, wie gerade schon gesagt, eine spezielle Zelle definieren. Nämlich die für die Progressbar. Es ist ein Handler der erst definiert werden muss, bevor er genutzt werden kann. Verändert sich der Wert der Zelle so wird dieser Handler aufgerufen und er verarbeitet die Änderung. Um genau zu sein ruft er dann die Klasse ProgressCell auf, die wiederum das Bild erstellt.

Alle Änderungen die das Aussehen der Progressbar-Zelle betreffen, werden in der Klasse „ProgressCell“ vorgenommen. Wir Hintergrundfarbe, Vordergrundfarbe, Textformatierung, usw.

Und das war es auch schon. Einfaches Prinzip, einfacher Code.

Ich hoffe das Hilft euch auch weiter… und mir beim nächsten mal auch wieder :)

Viele Grüße
Gordon

0 Antworten

Hinterlassen Sie einen Kommentar

Wollen Sie an der Diskussion teilnehmen?
Feel free to contribute!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.


*