ProgressBar wewnątrz DataGridView

Dzisiaj pokażę wam jak zrobić coś takiego jak na obrazku poniżej. Czyli jak dodać do naszego DatagridView  Progressbar.

progressbarwdatagridview

Każdemu zainteresowanemu systemami ERP takie rozwiązanie nie jest obce. Zaczynamy od nowego projektu i przenosimy na niego 2x DatagridView:

progressbar1

Po tej operacji nasza forma wygląda tak jak na zdjęciu:progressbar2

Teraz dodamy sobie klasę. Aby to zrobić przechodzimy do Projekt>>Dodaj formularz systemu Windows…..

progressbar3

Znajdujemy Klasę i nazywamy ją jak chcemy (ja nazwałem ją „Paseknaladowania.vb”)

progressbar4

Po utworzeniu klasy powinna ona pojawić się po prawej stronie w „Eksploratorze rozwiązań”:

progressbar5Otwieramy naszą klasę i wypełniamy ją kodem:

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Public Class DataGridViewProgressBarColumn
    Inherits DataGridViewTextBoxColumn

    'Konstruktor
    Public Sub New()
        Me.CellTemplate = New DataGridViewProgressBarCell()
    End Sub

    'Szablon komórek, ustawienia
    Public Overrides Property CellTemplate() As DataGridViewCell
        Get
            Return MyBase.CellTemplate
        End Get
        Set(ByVal value As DataGridViewCell)

            If Not TypeOf value Is DataGridViewProgressBarCell Then
                Throw New InvalidCastException("DataGridViewProgressBarCell")
            End If
            MyBase.CellTemplate = value
        End Set
    End Property

    ''Wartość maksymalna
    Public Property Maximum() As Integer
        Get
            Return CType(Me.CellTemplate, DataGridViewProgressBarCell).Maximum
        End Get
        Set(ByVal value As Integer)
            If Me.Maximum = value Then
                Return
            End If

            CType(Me.CellTemplate, DataGridViewProgressBarCell).Maximum = value

            If Me.DataGridView Is Nothing Then
                Return
            End If
            Dim rowCount As Integer = Me.DataGridView.RowCount
            Dim i As Integer
            For i = 0 To rowCount - 1
                Dim r As DataGridViewRow = Me.DataGridView.Rows.SharedRow(i)
                CType(r.Cells(Me.Index), DataGridViewProgressBarCell).Maximum = _
                    value
            Next i
        End Set
    End Property

    ''Wartość minimalna
    Public Property Mimimum() As Integer
        Get
            Return CType(Me.CellTemplate, DataGridViewProgressBarCell).Mimimum
        End Get
        Set(ByVal value As Integer)
            If Me.Mimimum = value Then
                Return
            End If

            CType(Me.CellTemplate, DataGridViewProgressBarCell).Mimimum = value

            If Me.DataGridView Is Nothing Then
                Return
            End If
            Dim rowCount As Integer = Me.DataGridView.RowCount
            Dim i As Integer
            For i = 0 To rowCount - 1
                Dim r As DataGridViewRow = Me.DataGridView.Rows.SharedRow(i)
                CType(r.Cells(Me.Index), DataGridViewProgressBarCell).Mimimum = _
                    value
            Next i
        End Set
    End Property
End Class

'Wyświetlanie ProgressBar w Datagridview

Public Class DataGridViewProgressBarCell
    Inherits DataGridViewTextBoxCell
    'Konstruktor
    Public Sub New()
        Me.maximumValue = 100
        Me.mimimumValue = 0
    End Sub

    Private maximumValue As Integer

    Public Property Maximum() As Integer
        Get
            Return Me.maximumValue
        End Get
        Set(ByVal value As Integer)
            Me.maximumValue = value
        End Set
    End Property

    Private mimimumValue As Integer

    Public Property Mimimum() As Integer
        Get
            Return Me.mimimumValue
        End Get
        Set(ByVal value As Integer)
            Me.mimimumValue = value
        End Set
    End Property
    'Określa typ danych w komurkach
    'Użyto wartości całkowitych
    Public Overrides ReadOnly Property ValueType() As Type
        Get
            Return GetType(Integer)
        End Get
    End Property
    'Określa wartość domyślną nowego rekordu, zmiana tego parametru powoduje 
    'automatyczne wstawianiewartości w nowe komurki
    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get
            Return 0
        End Get
    End Property

    Public Overrides Function Clone() As Object
        Dim cell As DataGridViewProgressBarCell = _
               CType(MyBase.Clone(), DataGridViewProgressBarCell)
        cell.Maximum = Me.Maximum
        cell.Mimimum = Me.Mimimum
        Return cell
    End Function

    Protected Overrides Sub Paint(ByVal graphics As Graphics, _
        ByVal clipBounds As Rectangle, _
        ByVal cellBounds As Rectangle, _
        ByVal rowIndex As Integer, _
        ByVal cellState As DataGridViewElementStates, _
        ByVal value As Object, _
        ByVal formattedValue As Object, _
        ByVal errorText As String, _
        ByVal cellStyle As DataGridViewCellStyle, _
        ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
        ByVal paintParts As DataGridViewPaintParts)

        'Ustala wartość
        Dim intValue As Integer = 0
        If TypeOf value Is Integer Then
            intValue = CInt(value)
        End If
        If intValue < Me.mimimumValue Then
            intValue = Me.mimimumValue
        End If
        If intValue > Me.maximumValue Then
            intValue = Me.maximumValue
        End If
        'Oblicza procent
        Dim rate As Double = CDbl(intValue - Me.mimimumValue) / (Me.maximumValue - Me.mimimumValue)

        'Rysuję linię granicy komórki (ramki)
        If (paintParts And DataGridViewPaintParts.Border) = DataGridViewPaintParts.Border Then
            Me.PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
        End If
        ' zasięg wewnątrz linii granicznej
        Dim borderRect As Rectangle = Me.BorderWidths(advancedBorderStyle)
        Dim paintRect As New Rectangle(cellBounds.Left + borderRect.Left, cellBounds.Top + borderRect.Top, cellBounds.Width - borderRect.Right, cellBounds.Height - borderRect.Bottom)

        Dim isSelected As Boolean = ((cellState And DataGridViewElementStates.Selected) = DataGridViewElementStates.Selected)
        Dim bkColor As Color
        If isSelected AndAlso (paintParts And DataGridViewPaintParts.SelectionBackground) = DataGridViewPaintParts.SelectionBackground Then
            bkColor = cellStyle.SelectionBackColor
        Else
            bkColor = cellStyle.BackColor
        End If
        'Rysuje tło
        If (paintParts And DataGridViewPaintParts.Background) = DataGridViewPaintParts.Background Then
            Dim backBrush As New SolidBrush(bkColor)
            Try
                graphics.FillRectangle(backBrush, paintRect)
            Finally
                backBrush.Dispose()
            End Try
        End If

        paintRect.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top)
        paintRect.Width -= cellStyle.Padding.Horizontal
        paintRect.Height -= cellStyle.Padding.Vertical
        'Rysowanie progressBar
        If (paintParts And DataGridViewPaintParts.ContentForeground) = _
            DataGridViewPaintParts.ContentForeground Then
            If ProgressBarRenderer.IsSupported Then
                'styl rysowania
                'rysowanie ramki
                'Jeśli usuniemy tę opcje nasz progressbar będzie wyglądał nago :P
                ProgressBarRenderer.DrawHorizontalBar(graphics, paintRect)
                'rysowanie paska
                Dim barBounds As New Rectangle(paintRect.Left + 3, paintRect.Top + 3, paintRect.Width - 4, paintRect.Height - 6)
                barBounds.Width = CInt(Math.Round((barBounds.Width * rate)))
                ProgressBarRenderer.DrawHorizontalChunks(graphics, barBounds)
                'zmiana koloru progress baru
                '''  graphics.FillRectangle(Brushes.Aqua, barBounds)
            Else
                'Jeżeli coś pójdzie nie tak powyżej nasz progressbar zostanie namalowany kodem poniżej
                'można przekopiować ten kod powyżej i zobaczyć jak to wygląda, mało ciekawie 
                graphics.FillRectangle(Brushes.White, paintRect)
                graphics.DrawRectangle(Pens.Black, paintRect)
                Dim barBounds As New Rectangle(paintRect.Left + 1, _
                    paintRect.Top + 1, _
                    paintRect.Width - 1, _
                    paintRect.Height - 1)
                barBounds.Width = CInt(Math.Round((barBounds.Width * rate)))
                graphics.FillRectangle(Brushes.Blue, barBounds)
            End If
        End If
        'zmiana ostrości ramek
        'chodzi tutaj o podświetlenie kropkami po wybraniu komurki i ostrość krawędzi tego podświetlenia
        If Me.DataGridView.CurrentCellAddress.X = Me.ColumnIndex AndAlso Me.DataGridView.CurrentCellAddress.Y = Me.RowIndex AndAlso _
            (paintParts And DataGridViewPaintParts.Focus) = DataGridViewPaintParts.Focus AndAlso Me.DataGridView.Focused Then
            Dim focusRect As Rectangle = paintRect
            focusRect.Inflate(-3, -3)
            ControlPaint.DrawFocusRectangle(graphics, focusRect)
        End If
        'wyświetlanie tekstu
        If (paintParts And DataGridViewPaintParts.ContentForeground) = _
            DataGridViewPaintParts.ContentForeground Then
            'określanie tekstu który będzie wyświetlany
            Dim txt As String = String.Format("{0}%", Math.Round((rate * 100)))
            Dim flags As TextFormatFlags = _
                TextFormatFlags.HorizontalCenter Or _
                    TextFormatFlags.VerticalCenter
            'kolor tekstu
            Dim fColor As Color = cellStyle.ForeColor
            paintRect.Inflate(-2, -2)
            TextRenderer.DrawText( _
                graphics, txt, cellStyle.Font, paintRect, fColor, flags)
        End If
        'Wyświetlanie ikon błędu
        If (paintParts And DataGridViewPaintParts.ErrorIcon) = _
                DataGridViewPaintParts.ErrorIcon AndAlso _
            Me.DataGridView.ShowCellErrors AndAlso _
            Not String.IsNullOrEmpty(errorText) Then
            Dim iconBounds As Rectangle = _
                Me.GetErrorIconBounds(graphics, cellStyle, rowIndex)
            iconBounds.Offset(cellBounds.X, cellBounds.Y)
            Me.PaintErrorIcon(graphics, iconBounds, cellBounds, errorText)
        End If
    End Sub
End Class

Ważniejsze rzeczy opisałem w kodzie. Aby zmienić kolor z zielonego na wybrany przez siebie należy aktywować w kodzie opcje:

 ProgressBarRenderer.DrawHorizontalChunks(graphics, barBounds)
                'zmiana koloru progress baru
                '''  graphics.FillRectangle(Brushes.Aqua, barBounds)

który jest w 199 linijce kodu. Należy wybrać kolor po słowie „Brushes.(nasz kolor)”. W skrypcie powyżej macie kolor Aqua po aktywowaniu skryptu progressbar będzie wyglądał tak:

progressbar14

Mamy gotową klasę, trzeba ją teraz wykorzystać. Pokażę wam dwa sposoby które można wykorzystać.

Pierwszy z nich to dodanie danych przy Form_Load. Wygląda to tak:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim pbColumn As New DataGridViewProgressBarColumn()
        DataGridView1.ColumnCount = 2
        DataGridView1.Columns(0).Name = "pierwsza"
        DataGridView1.Columns(0).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
        DataGridView1.Columns(1).Name = "drugi"
        DataGridView1.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
        DataGridView1.Columns.Add(pbColumn)
        DataGridView1.Columns(2).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
        pbColumn.HeaderText = "test"

        DataGridView1.Rows.Add()
        DataGridView1.Rows(0).Cells(0).Value = "test"
        DataGridView1.Rows(0).Cells(1).Value = "test"
        DataGridView1.Rows(0).Cells(2).Value = 25
        DataGridView1.Rows.Add()
        DataGridView1.Rows(1).Cells(0).Value = "test2"
        DataGridView1.Rows(1).Cells(1).Value = "test2"
        DataGridView1.Rows(1).Cells(2).Value = 60
        DataGridView1.Rows.Add()
        DataGridView1.Rows(2).Cells(0).Value = "test3"
        DataGridView1.Rows(2).Cells(1).Value = "test3"
        DataGridView1.Rows(2).Cells(2).Value = 50
    End Sub

Po uruchomieniu programu efekt będzie taki:

progressbar6Dobra a jak użyć tego skryptu gdy mamy bazę danych typu *.mdf albo bazę danych na serwerze msql, bardzo prosto. Na potrzeby tego tutoriala dodałem sobie zwykłą lokalną bazę danych  którą następnie wypełniłem danymi jak na obrazku.

progressbar8Następnie dodałem źródło danych:

progressbar9

 

Następnie dodałem te dane (przenosząc je) do DatagridView2. Po odpaleniu wygląda to tak:

progressbar10

Aby ostatnia kolumna wyświetlała ProgressBar należy w projektancie „Edytować kolumny”:

progressbar11

Znajdujemy po lewej stronie naszą kolumnę i zmieniamy jej „Column Type” i wybieramy „DatagridViewProgressBarColumn”

progressbar12

Po tej operacji mamy już wewnątrz DatagridView ProgressBar:

progressbar13

Tym sposobem mamy fajny i dosyć elastyczny ProgressBar wewnątrz DatagridView. Tak jak zawsze projekt do pobrania macie tutaj: prograss bar w datagridview

Permalink do tego artykułu: https://visualmonsters.cba.pl/progressbar-wewnatrz-datagridview/

Dodaj komentarz

Twój adres email nie będzie publikowany.