vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Schützen Sie Ihre Software vor Software-Piraterie - mit sevLock 1.0 DLL!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Controls · DataGrid & DataGridView   |   VB-Versionen: VB2005, VB200810.06.08
Anzeige eines Daten-Array im DatagridView

Einstellungen des DatagridView zur Anzeige von Daten in einem zweidimensionalen Double-Array

Autor:   Manfred BohnBewertung:     [ Jetzt bewerten ]Views:  32.695 
ohne HomepageSystem:  Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Das DataGridView-Steuerelement bietet eine Vielzahl von Möglichkeiten, um Daten aller Art anzuzeigen und zu editieren. Zu diesem Zweck stellt es eine Reihe von Objekten zur Verfügung, deren Methoden und Eigenschaften aber nur mit einiger Übung zu überblicken sind und zielgerichtet angewendet werden können.

Erschwert wird die Verwendung des Steuerelements, weil manche Eigenschaften von anderen "überschrieben" werden und weil ein Teil der Objekte in Hierarchien angeordnet sind. Einstellungen der übergeordneten Objekte blockieren die untergeordneten; aber nur, falls sie auch 'gesetzt' worden sind.

Was diesem Steuerelement fehlt, sind Methoden, die auf einfache Weise jeweils eine bestimmte Anwendungsfunktionalität bereitstellen.

Zur Demonstration, was damit gemeint ist, dient die Klasse 'cArrayGrid'.
Das DataGridView wird verwendet, um den Inhalt eines Double-Array anzuzeigen.

Einige Vorüberlegungen zur Gestaltung der Funktionalität:

  1. Die Anordnung der Daten in einem Array wírd üblicherweise als 'fixiert' betrachtet, weil Arrays - wie Datenbanktabellen - meist Datenaggregate (z.B. Matrizen) enthalten. Bei der Anzeige ist das Hinzufügen, Löschen, Sortieren, Verschieben oder Auswählen von Zeilen und Spalten deshalb nicht zuzulassen.
     
  2. Der Datentyp 'Double' stellt einen 'breiten Datenraum' zur Verfügung. (Man vergleiche Double.Epsilon mit Double.MaxValue.) Bei der Anzeige möchte man aber übersichtliche Spalten haben, in denen der Dezimalpunkt stets an der gleichen Stelle steht. Dabei soll die Zahl der jeweils angezeigten Nachkommastellen automatisch an den Dateninhalt der Spalte angepasst werden.
    Auch zu einem Mix mit Werten, die sinnvoll nur in Exponentialdarstellung angezeigt werden können, sollte es nicht kommen. Absolut extrem hohe Werte (meist ohnehin Ausreißer oder das Resultat von Berechnungsfehlern) sollen ausgefiltert sein. Die 'rohen' Daten müssen aber - z.B. in Form von Tooltips - in der Ansicht zur Verfügung stehen.
     
  3. Die Breite der Spalten sollte jeweils an den Dateninhalt angepasst sein.
    (Während die Daten innerhalb einzelner Spalten oft in einem begrenzten Wertebereich liegen, trifft dies zwischen den Spalten mitunter nicht zu.)

Der Konstruktor der Klasse 'cArrayGrid' erledigt die Aufgabe.

Neben dem anzuzeigenden Array können vier optionale Boolean-Parameter übergeben werden:

  • 'HeadersVisible' legt fest, ob die Array-Indices in den Zeilen- und Spaltenköpfen angezeigt (true) oder ob sie als Zell-Tooltip aufbereitet (false) werden.
  • 'AllowResizing' legt fest, ob die Spaltenbreite und Zeilenhöhe mit der Maus zu ändern sind.
  • 'ShowToolTips' legt fest, ob Zellen-ToolTips angezeigt werden.
  • 'DisplayExponential' erlaubt die Exponentialdarstellung übergroßer Zahlen.

Schritte zur Ausführung des Anwendungsbeispiels:

  1. Ein neues Projekt erstellen (WindowsApplication)
  2. Ein neues Klassenmodul hinzufügen und den Code von 'cArrayGrid' eintragen
  3. In die FormLoad-Prozedur von 'Form1' den Code des Anwendungs-Beispiels eintragen
  4. Den Debugger starten
    (Man kann natürlich eine Instanz von 'cArrayGrid' auch im Deklarationsteil des Formulars mit 'WithEvents' erstellen und deren Ereignisse verarbeiten.)

Code der Klasse 'cArrayGrid'

Option Strict On
Option Explicit On
 
''' <summary>
''' Klasse zur Anzeige eines Double-Array in einem DataGridView-Steuerelement
''' </summary>
Public Class cArrayGrid
 
  Inherits DataGridView
 
  ' Maximal angezeigte Datenausprägung (ohne Expo-Darstellung)
  Const cMaxValue As Double = 100000000.0
  ' Maximal angezeigte Zahl der Nachkommastellen
  Const cMaxDigits As Integer = 10
 
  ' Anzeige-Font
  Private gFont As Drawing.Font = _
    New Drawing.Font("Arial", 14, _
    FontStyle.Regular, GraphicsUnit.Pixel)
 
  ' Zum Spoeichern der Werte der Optionalen Konstruktor-Parameter
  Dim gHeadersVisible As Boolean      ' Zeilen-/Spaltenköpfe sichtbar?
  Dim gAllowResizing As Boolean       ' Zeilen-/Spaltenbreite variabel?
  Dim gShowTooltips As Boolean        ' Anzeige von Zell-Tooltips?
  Dim gDisplayExponential As Boolean  ' Daten in Exponentialdarstellung? 
 
  Dim gArr(,) As Double               ' Speicher für Array-Daten
  ''' <param name="arr">Double-Array (Rank = 2), 
  ''' dessen Elemente angezeigt werden sollen</param>
  ''' <param name="HeadersVisible">Zeilen-/Spaltenköpfe sichtbar?</param>
  ''' <param name="AllowResizing">Zeilenhöhe/Spaltenbreite einstellbar?</param>
  ''' <param name="ShowTooltips">Anzeige von Zell-Tooltips?</param>
  ''' <param name="DisplayExponential">Bei übergroßen Zahlen:
  ''' Exponentialdarstellung zulassen</param>
  Public Sub New(ByVal arr(,) As Double, _
    Optional ByVal HeadersVisible As Boolean = True, _
    Optional ByVal AllowResizing As Boolean = False, _
    Optional ByVal ShowTooltips As Boolean = True, _
    Optional ByVal DisplayExponential As Boolean = False)
 
    ' Parameter-Werte speichern
    gHeadersVisible = HeadersVisible
    gAllowResizing = AllowResizing
    gShowTooltips = ShowTooltips
    gDisplayExponential = DisplayExponential
 
    If IsNothing(arr) Then Exit Sub
 
    gArr = CType(arr.Clone, Double(,))
 
    CType(Me, System.ComponentModel. _
    ISupportInitialize).BeginInit()
    Me.SuspendLayout()
 
    ' Grid-Grundeinstellungen
    InitGrid()
 
    If Not IsNothing(arr) Then
      ' Daten ins Grid eintragen
      FillGrid()
      ' Spaltenansicht einrichten
      InitColumns()
    End If
 
    CType(Me, System.ComponentModel. _
    ISupportInitialize).EndInit()
    Me.ResumeLayout(True)
  End Sub
  Private Sub InitGrid()
 
    ' Grundeinstellungen des DataGridView
    ' vor der Zuweisung von Array-Daten
 
    ' AlternatingRow-Hintergrundfarbe
    Dim gray245 As System.Drawing.Color = _
    Color.FromArgb(255, 245, 245, 245)
 
    ' Cursor-Hintergrundfarbe
    Dim gray230 As System.Drawing.Color = _
    Color.FromArgb(255, 230, 230, 230)
 
    With Me
      ' Grid-Einstellungen
      ' ==================
      If gHeadersVisible Then
        .ClipboardCopyMode = _
        DataGridViewClipboardCopyMode. _
        EnableAlwaysIncludeHeaderText
      Else
        .ClipboardCopyMode = _
        DataGridViewClipboardCopyMode. _
        EnableWithoutHeaderText
      End If
 
      ' Einfügen, Löschen, Umordnen verbieten
      .AllowDrop = False
      .AllowUserToAddRows = False
      .AllowUserToDeleteRows = False
      .AllowUserToOrderColumns = False
 
      .AllowUserToResizeRows = gAllowResizing
 
      ' Maus-Click auf Column/Rowheader soll NICHT
      ' zur Markierung führen
      .SelectionMode = _
      DataGridViewSelectionMode.CellSelect
      ' Keine Auswahl erlauben, weil 
      ' Daten nur angezeigt werden
      .MultiSelect = False
 
      .BorderStyle = _
      Windows.Forms.BorderStyle.Fixed3D
 
      ' Farbe des nicht mit Zellen belegten 
      ' GridView-Hintergrundes
      .BackgroundColor = Color.DarkGray
 
      ' Nur bei 'Bedarf' werden die Scrollbars angezeigt
      ' (durch eine andere Einstellung dieser Eigenschaft
      ' kann man sie aber am Erscheinen hindern)
      .ScrollBars = Windows.Forms.ScrollBars.Both
 
 
      ' ColumnHeader-Einstellungen
      ' ==========================
      .ColumnHeadersVisible = gHeadersVisible
 
      .ColumnHeadersHeightSizeMode = _
      DataGridViewColumnHeadersHeightSizeMode. _
      AutoSize
 
      .ColumnHeadersBorderStyle = _
      DataGridViewHeaderBorderStyle.Raised
 
      With .ColumnHeadersDefaultCellStyle
        .Font = gFont
        .ForeColor = Color.Black
        .BackColor = gray230
        .Alignment = _
        DataGridViewContentAlignment. _
        TopLeft
      End With
 
      ' RowHeader-Einstellungen
      ' =======================
      .RowHeadersVisible = gHeadersVisible
 
      .RowHeadersWidthSizeMode = _
      DataGridViewRowHeadersWidthSizeMode. _
      AutoSizeToAllHeaders
 
      .RowHeadersBorderStyle = _
      .ColumnHeadersBorderStyle
 
      ' von oben übernehmen
      .RowHeadersDefaultCellStyle = _
      .ColumnHeadersDefaultCellStyle
 
      ' Row-Einstellungen
      ' =================
      With .RowsDefaultCellStyle
        ' Zahlen werden nach rechts ausgerichtet
        .Alignment = _
        DataGridViewContentAlignment.MiddleRight
        .BackColor = Color.White
        .ForeColor = Color.Black
        .Format = "0.00000000"
        .NullValue = "???"  'NaN
        ' 'Cursor'-Farbe
        .SelectionBackColor = gray230
        .SelectionForeColor = Color.Black
        .Font = gFont
      End With
 
      With .AlternatingRowsDefaultCellStyle
        ' für bessere Lesbarkeit der DatenZeilen
        .BackColor = gray245
      End With
 
 
      ' Weitere allgemeine Eigenschaften
      ' ================================
      .TopLeftHeaderCell.Value = "--> Clipboard"
      .TopLeftHeaderCell.ToolTipText = _
        "Doppel-Click kopiert die Daten"
      .ShowCellToolTips = gShowTooltips
      .Cursor = Cursors.Arrow
 
      .DoubleBuffered = True
      .ResizeRedraw = True
      .GridColor = Color.DarkBlue
 
    End With
  End Sub
  Private Sub FillGrid()
 
    ' Die Arraydaten werden in das GridView eingetragen
 
    Dim r, c As Integer     ' Loops
    Dim wert As Double      ' Inhalt Array-Element
    Dim tt As String        ' Tooltip
 
    Dim rows As DataGridViewRowCollection = MyBase.Rows
 
    ' Daten Löschen
    MyBase.Columns.Clear()
    MyBase.Rows.Clear()
 
    ' Spalten erstellen
    For c = 0 To UBound(gArr, 2)
      ' ArrayIndex in Spaltenkopf eintragen
      MyBase.Columns.Add(CStr(c), "Col_" + CStr(c))
    Next c
 
    ' Für jede Spalte: Anzeigeformat ermitteln
    Dim fmt() As String = CreateFormat(gArr)
 
    ' Die erforderliche Anzahl Zeilen in einem
    ' Rutsch erstellen:
    MyBase.Rows.Add(gArr.GetLength(0))
 
    ' Daten ins DatagridView eintragen
    For r = 0 To UBound(gArr, 1)
      With rows(r)
        ' Zeileneigenschaften festlegen:
        ' Keine 'verschwindende' Zeile zulassen
        .MinimumHeight = 20
        ' Fetter Strich zwischen den Zeilen  
        .DividerHeight = 2
 
        ' Zeile r mit Werten füllen
        For c = 0 To UBound(gArr, 2)
          wert = gArr(r, c)
          tt = ""          ' Tooltip Initialisieren
 
          With .Cells(c)
            ' Array-Element: 
            ' Inhalt der Zelle aufbereiten
 
            .Tag = wert ' Original-Wert aufbewahren
 
            If Math.Abs(wert) <= cMaxValue Then
              ' Anzuzeigender Wert (formatiert)
              .Value = Format(wert, fmt(c))
              If Math.Abs(wert - CDbl(.Value)) >= _
                Double.Epsilon Then
                ' Anzeige weicht vom Array-Wert ab:
                ' Wert in ToolTip eintragen
                tt = CStr(wert)
              End If
            ElseIf Double.IsNaN(wert) Then
              ' Keine Zahl: NullValue wird angezeigt
              .Value = Nothing
              tt = "Not A Number!!"
            ElseIf wert > cMaxValue Then
              If gDisplayExponential Then
                ' Exponentialdarstellung
                .Value = Format(wert, "0.##########E+000")
              Else
                ' übergroßer Wert
                .Value = " > MaxValue"
              End If
              tt = CStr(wert)
            ElseIf wert < cMaxValue Then
              If gDisplayExponential Then
                ' Exponentialdarstellung
                .Value = Format(wert, "0.##########E+000")
              Else
                ' zu kleiner Wert
                .Value = " < MinValue"
              End If
              tt = CStr(wert)
            End If
 
            If gHeadersVisible = False Then
              If tt <> "" Then tt += vbCrLf
              ' Array-Indizierung in Tooltip eintragen
              tt = "Arr(" + CStr(r) + "," + CStr(c) + ")"
            End If
            If gShowTooltips Then
              ' Zell-Tooltip erstellen
              .ToolTipText = tt
            End If
          End With
        Next c
        ' Array-Index in den Zeilenkopf eintragen
        .HeaderCell.Value = "Row_" + CStr(r)
      End With
    Next r
  End Sub
  Private Sub InitColumns()
 
    ' die meisten allgemeinen Einstellungen der Spalten
    ' müssen in jeder einzelnen Spalte vorgenommen werden
 
    Dim c As Integer
    Dim col As DataGridViewColumn
 
    ' Dim cw(Me.ColumnCount - 1) As Integer
 
    For c = 0 To MyBase.Columns.Count - 1
      col = MyBase.Columns(c)
      With col
        ' Fetter Spalten-Trennstrich
        .DividerWidth = 2
        ' Sortieren der Spalte abschalten
        .SortMode = _
        DataGridViewColumnSortMode.NotSortable
 
        If gAllowResizing Then
          ' User kann die Spaltenbreite mit der Maus ändern
          .AutoSizeMode = _
          DataGridViewAutoSizeColumnMode.None
          .Resizable = DataGridViewTriState.True
 
          ' Einstellung der Spaltenbreite initialisieren
          ' (!! Diese Methode schluckt ggf. Rechenzeit !!) 
          .Width = .GetPreferredWidth( _
            DataGridViewAutoSizeColumnMode. _
            AllCellsExceptHeader, True)
 
          ' keine 'verschwindende' Spalte zulassen
          ' zu kleines Width wird ggf. automatisch angepasst
          .MinimumWidth = 60
        Else
          ' Spaltenbreite wird anhand der Daten festgelegt 
          ' und ist fixiert 
          .AutoSizeMode = _
           DataGridViewAutoSizeColumnMode. _
           AllCellsExceptHeader
        End If
 
        .ValueType = GetType(Double)
 
        ' nur Anzeige der Daten, kein Editieren zulassen
        .ReadOnly = True
        .Visible = True
      End With
    Next c
  End Sub
  Private Function CreateFormat(ByVal arr(,) As Double) As String()
 
    ' Zahl der erforderlichen Nachkommastellen 
    ' in den einzelnen Spalten ermitteln
 
    Dim r, c As Integer                ' Loops
    Dim str As String                  ' Format-String
    Dim fmt(UBound(arr, 2)) As String  ' Rückgabe
 
    ' Kulturspezifischer Dezimalpunkt 
    Dim dec_sep As String = _
    My.Application.Culture.NumberFormat. _
    NumberDecimalSeparator
 
    Dim dp, nk, nk_max As Integer
 
    For c = 0 To UBound(arr, 2)
      fmt(c) = "0." 'G anzzahlformat
      nk_max = 0
      For r = 0 To UBound(arr, 1)
        If arr(r, c) <= cMaxValue Then
 
          ' Verwendung des Standard-Dezimalpunktes
          ' in der Formatanweisung
          str = Format(arr(r, c), _
              "0.################")
 
          ' Im formatierten String steht der 
          ' kulturspezifische Dezimalpunkt 
          dp = InStr(str, dec_sep)
 
          If dp > 0 Then
            nk = Len(str) - dp
          End If
          If nk_max < nk Then nk_max = nk
        End If
      Next r
 
      If nk_max > cMaxDigits Then nk_max = cMaxDigits
      If nk_max > 0 Then
        ' erforderliche Nachkommastellen
        fmt(c) += New String("0"c, nk_max)
      End If
    Next c
 
    Return fmt
  End Function
  ''' <summary>
  ''' Positionieren des DataGridView auf einem Formular
  ''' </summary>
  ''' <param name="Parent">zugeordnetes Formular</param>
  ''' <param name="Top">Oben (Position y-Achse)</param>
  ''' <param name="Left">Links (Position x-Achse)</param>
  ''' <param name="Width">Breite des DataGridView</param>
  ''' <param name="Height">Höhe des DataGridView</param>
  Public Shadows Sub Location(ByVal Parent As Windows.Forms.Form, _
    ByVal Top As Integer, ByVal Left As Integer, _
    ByVal Width As Integer, ByVal Height As Integer)
 
    MyBase.Parent = Parent
    MyBase.Width = Width
    MyBase.Height = Height
    MyBase.Top = Top
    MyBase.Left = Left
  End Sub
  Private Sub cArrayGrid_MouseDoubleClick(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) _
    Handles Me.MouseDoubleClick
 
    ' Daten im  HTML-Format in die Zwischenablage übertragen
 
    Dim r As Integer
 
    If e.X < Me.RowHeadersWidth And e.Y < Me.ColumnHeadersHeight Then
      ' Doppelclick auf die linke obere Zelle ist erfolgt:
 
      If Clipboard.ContainsData(DataFormats.Text) Then _
          If MsgBox("Zwischenablage enthält bereits Text - Löschen?", _
              MsgBoxStyle.Question Or MsgBoxStyle.OkCancel, _
              "cArrayGrid") = MsgBoxResult.Cancel Then Exit Sub
 
      My.Application.DoEvents()
 
      ' Alle Zeilen markieren
      Me.SelectionMode = DataGridViewSelectionMode.FullRowSelect
      Me.MultiSelect = True
      For r = 0 To Me.RowCount - 1
        MyBase.Rows(r).Selected = True
      Next r
 
      ' Die markierten Daten werden in die Zwischenablage kopiert
      ' Im HTML-Format kopiert und dann in eine Datei eingetragen, 
      ' lassen sich die Daten ganz ordentlich im Browser betrachten
      ' Das direkte Einfügen in ein Excel-Arbeitsblatt ist möglich
      Clipboard.SetDataObject( _
        Me.GetClipboardContent.GetData(DataFormats.Html), True)
 
      ' Markieren von Zeilen wieder sperren
      Me.SelectionMode = DataGridViewSelectionMode.CellSelect
      Me.MultiSelect = False
      Me.Update()
 
      MsgBox("Die Daten sind in die Zwischenablage kopiert worden", _
      MsgBoxStyle.Information, "cArrayGrid")
    End If
  End Sub
  ''' <summary>
  ''' Abfrage eines Array-Elements
  ''' </summary>
  ''' <param name="RowIndex">Index 1. Arraydimension</param>
  ''' <param name="ColumnIndex">Index 2. Arraydimension</param>
  ''' <returns>Inhalt des Array-Elements: Double-Wert</returns>
  Default Public Shadows ReadOnly Property Item(ByVal RowIndex As Integer, _
    ByVal ColumnIndex As Integer) As Double
    ' Überschattung der Standard-Eigenschaft des DataGridView
    ' Sie wird 'ReadOnly' und liefert einen Double-Wert zurück,
    ' ---> den Inhalt des entsprechenden Array-Elements 
    ' (deshalb: geänderte Parameter-Reihenfolge!)
    Get
      Try
        Return CDbl(MyBase.Rows(RowIndex).Cells(ColumnIndex).Tag)
      Catch
        ' falls ungültige Indices verlangt werden
        Return Double.NaN
      End Try
    End Get
  End Property
End Class

Das Anwendungsbeispiel

Public Class Form1
 
  Private Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
 
    ' ==========================================
    ' Anwendungsbeispiel
    ' ==========================================
 
    ' Einige Formular-Eigenschaften ...
    Me.MinimumSize = New Drawing.Size(500, 500)
    Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Fixed3D
    Me.Visible = False
 
    ' Einige Daten erstellen
    Dim M As Integer = 15
    Dim N As Integer = 1500
    Dim arr(N, M) As Double
    Dim r, c As Integer
 
    For c = 0 To M
      For r = 0 To N
        arr(r, c) = 1000000000 * Rnd() + Math.Round(Rnd(), c)
        arr(r, c) = Math.Round(Rnd(), c)
        arr(r, c) = r + c + arr(r, c)
      Next r
    Next c
 
    ' SO EINFACH könnte BASIC sein:
    ' =============================
 
    ' Der Konstruktor der Klasse befördert die
    ' Array-Daten ins DataGridView und setzt Eigenschaften
    Dim ag As New cArrayGrid(arr, , True)
 
    ' Die Location-Methode ordnet SE dem Formular zu, 
    ' positioniert es und richtet seine Größe ein
    ag.Location(Me, 10, 10, Me.Width - 30, Me.Height - 50)
 
    Me.Show()
    ' ==========================================
    ' Ende des Anwendungsbeispiels
    ' ==========================================
  End Sub
 
End Class

Dieser Tipp wurde bereits 32.695 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel