Announcement

Collapse
No announcement yet.

Datagridview an Array binden

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Datagridview an Array binden

    Hallo,

    ich habe ein Array, das ich gern als Datenquelle für ein Datagridview verwenden möchte. nachdem was ich im Netz gefunden habe, sollte das ganz einfach funktionieren, nur bei mir klappt es nicht.

    hier mal der Code:

    Code:
    Dim array(,) As Object = r.Value(Excel.XlRangeValueDataType.xlRangeValueDefault)
    Dim bound0 as integer = array.GetUpperBound(0)
    dim bound1 as Integer = array.GetUpperBound(1)
    
                   For j As Integer = 1 To bound0
    
    
                        For x As Integer = 1 To bound1
                            Dim s1 As String = array(j, x)
                            Console.Write(s1)
                            Console.Write(" "c)
                        Next
                        Console.WriteLine()
                    Next
    
                    GridExcel.DataSource = array
    In der Ausgabe ist das Array gefüllt, aber im grid wird nichts angezeigt.

    Kann jemand helfen?

    Besten dank schon mal
    Karline

  • #2
    Ein DataGridView kann mit eindimensionalen Listen umgehen. Wobei dann jedes Objekt in der Liste eine Zeile darstellt. Die Spalten sind dann halt die Properties dieses einen Objekts.
    Du hast aber ein zweidimensionale Liste wo jedes Array Element eine Zelle beschreibt. So funktioniert DataBinding nicht. Das mußt du anders lösen.

    PS. Sicherheitshalber ein Rat hinterher, da du mit Excel arbeitest, und du dich vielleicht wunderst das das hier nicht paßt. Ein Sheet ist etwas völlig anderes als eine Tabelle. Die können ähnlich aussehen sind aber auch nur das "ähnlich aussehend" und haben wenig mehr gemein.

    Comment


    • #3
      Wie bereits von Ralf Jansen festgestellt benötigt die DataGridView ein eindimensionales Array, um Daten zeilenweise darzustellen. Die Spalten bilden die Eigenschaften einer Zeile. Daher führt der schlichte Ansatz, das zweidimensionale Objekt-Array in ein eindimensionales Array von Object()-Arrays per Kopie der Daten zu wandeln und dieses neue Objekt der DataGridView.DataSource-Eigenschaft zuzuweisen, nicht zum Ziel. Es werden zwar Zeilen angezeigt, die Spalten sind aber die öffentlichen Eigenschaften einer Objekt-Array-Instanz.
      Dennoch ist mit geringem Aufwand das zweidimensionale Objekt-Array in einer DataGridView anzuzeigen: es bedarf einer Klasse Table, die die Aufgabe der Row-Auflistung übernimmt und durch Implementierung der Schnittstelle System.ComponentModel.ITypedList als Spalten Column0 bis ColumnX anbietet. Die Klasse Row ermöglicht den Zugriff auf die Spalten einer Zeile per Index. Die Klasse PropertyDescriptor ermöglicht, die "virtuellen" Eigenschaften eines Row-Objektes (Column0 bis ColumnX) zu definieren und implementiert via GetValue() bzw. SetValue() den lesenden bzw. schreibenden Zugriff auf eine Zelle im zweidimensionalen Objekt-Array.

      Klasse Row:
      [Highlight=vbnet] ''' <summary>
      ''' Primitive Form einer Row innerhalb eines zweidimensionalen Objekt-Arrays
      ''' </summary>
      ''' <remarks>
      ''' Im Konstruktor wird die Row des Objekt-Arrays durch den rowIndex festgelegt.
      ''' Per Property Item erfolgt der Zugriff auf eine Spalte dieser Zeile.
      ''' </remarks>
      Public Class Row

      Private _data As Object(,)
      Private _rowIndex As Integer
      Public Sub New(data As Object(,), rowIndex As Integer)
      _data = data
      _rowIndex = rowIndex
      End Sub
      Default Public Property Item(columnIndex As Integer) As Object
      Get
      Return _data(_rowIndex, columnIndex)
      End Get
      Set(value As Object)
      _data(_rowIndex, columnIndex) = value
      End Set
      End Property
      End Class
      [/Highlight]

      Klasse Table:
      [Highlight=vbnet]
      ''' <summary>
      ''' Primitive Form einer Table, die als Auflistung von Rows implementiert ist.
      ''' Sie implementiert die Schnittstelle ITypedList, damit nicht die Eigenschaften
      ''' einer Row-Instanz als Spalten in einer DataGridView erscheinen, sondern die
      ''' Spalten des zugrunde gelegten zweidimensionalen Objekt-Arrays.
      ''' </summary>
      ''' <remarks></remarks>
      Public Class Table
      Inherits System.Collections.Generic.List(Of Row)
      Implements System.ComponentModel.ITypedList

      ''' <summary>
      ''' Spalten der Tabelle (durch zweidimensionales Objekt-Array vorgegeben)
      ''' </summary>
      ''' <remarks></remarks>
      Private _columns As System.ComponentModel.PropertyDescriptor()
      Public Sub New(data As Object(,))
      'Anlegen der vorhanden Zeilen im Array
      For rowIndex As Integer = data.GetLowerBound(0) To data.GetUpperBound(0)
      Add(New Row(data, rowIndex))
      Next
      'Anlegen der vorhandenen Spalten im Array
      Dim lBound As Integer = data.GetLowerBound(1)
      Dim uBound As Integer = data.GetUpperBound(1)
      _columns = Array.CreateInstance(GetType(System.ComponentModel .PropertyDescriptor), uBound - lBound + 1)
      For columnIndex As Integer = lBound To uBound
      _columns(columnIndex - lBound) = New PropertyDescriptor(columnIndex)
      Next
      End Sub

      ''' <summary>
      ''' Spalten als PropertyDescriptorCollection zur Verfügung stellen
      ''' </summary>
      ''' <param name="listAccessors">nicht berücksichtigt</param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Function GetItemProperties(listAccessors() As System.ComponentModel.PropertyDescriptor) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ITypedList.GetItemProperties
      Return New System.ComponentModel.PropertyDescriptorCollection (_columns)
      End Function

      Public Function GetListName(listAccessors() As System.ComponentModel.PropertyDescriptor) As String Implements System.ComponentModel.ITypedList.GetListName
      Return "Table"
      End Function
      End Class
      [/Highlight]

      Klasse PropertyDescriptor:
      [Highlight=vbnet]
      ''' <summary>
      ''' PropertyDescriptor für Zugriff auf eine Zelle im zweidimensionalen Objekt-Array
      ''' </summary>
      ''' <remarks></remarks>
      Public Class PropertyDescriptor
      Inherits System.ComponentModel.PropertyDescriptor

      Private _columnIndex As Integer
      Public Sub New(columnIndex As Integer)
      MyBase.New("Column" & columnIndex, New System.Attribute() {})
      _columnIndex = columnIndex
      End Sub

      Public Overrides Function CanResetValue(component As Object) As Boolean
      Return True
      End Function

      Public Overrides ReadOnly Property ComponentType As System.Type
      Get
      Return GetType(Row)
      End Get
      End Property

      ''' <summary>
      ''' Lesender Zugriff auf eine Zelle des zweidimensionalen Objekt-Arrays
      ''' </summary>
      ''' <param name="component"></param>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Overrides Function GetValue(component As Object) As Object
      Return CType(component, Row).Item(_columnIndex)
      End Function

      Public Overrides ReadOnly Property IsReadOnly As Boolean
      Get
      Return False
      End Get
      End Property

      Public Overrides ReadOnly Property PropertyType As System.Type
      Get
      Return GetType(Object)
      End Get
      End Property

      ''' <summary>
      ''' Initialisierung einer Zelle (Zelle wird mit Nothing initialisiert)
      ''' </summary>
      ''' <param name="component"></param>
      ''' <remarks></remarks>
      Public Overrides Sub ResetValue(component As Object)
      CType(component, Row).Item(_columnIndex) = Nothing
      End Sub

      ''' <summary>
      ''' Schreibender Zugriff auf eine Zelle des zweidimensionalen Objekt-Arrays
      ''' </summary>
      ''' <param name="component"></param>
      ''' <param name="value"></param>
      ''' <remarks></remarks>
      Public Overrides Sub SetValue(component As Object, value As Object)
      CType(component, Row).Item(_columnIndex) = value
      End Sub

      Public Overrides Function ShouldSerializeValue(component As Object) As Boolean
      Return False
      End Function
      End Class
      [/Highlight]

      Damit ergibt sich die Zuweisung aus dem gegebenen Beispiel:
      GridExcel.DataSource = New Table(array)
      Zuletzt editiert von akk; 24.04.2013, 15:54. Reason: Anpassung auf nicht-null-indiziertes data-Array

      Comment


      • #4
        Hallo akk,

        besten Dank für den Code.

        Ich bekomme aber leider einen Fehler in der Zeile:
        Code:
        MyBase.New("Column" & columnIndex, {})
        Bei den geschwungenen Klammern bekomme ich : "Ausdruck erwartet".

        Kannst Du mir nochmal helfen?

        Besten Dank
        Karline

        Comment


        • #5
          Der Basiskonstruktor benötigt ein Array von Attribute-Objekten. Die angefragte Zeile lautet in der "korrekten" Schreibweise:
          MyBase.New("Column" & columnIndex, New System.Attribute(){})

          Comment


          • #6
            Danke akk,

            Kompilieren ist nun kein Problem, wenn ich es ausführe gib es Probleme mit den Indizes hier beim zugriff:

            Code:
            Default Public Property Item(ByVal columnIndex As Integer) As Object
                    Get
                        Return _data(_rowIndex, columnIndex)
                    End Get
                    Set(ByVal value As Object)
                        _data(_rowIndex, columnIndex) = value
                    End Set
                End Property
            Zugriff begint bei Index (0,0), schaue ich mir aber das _data-Array an, bedinnt dieses bei (1,1).

            Ich habe hier an dieser Stelle den Index von 0 auf 1 geändert
            Code:
                   For rowIndex As Integer = 1 To data.GetUpperBound(0)
                        Add(New Row(data, rowIndex))
                    Next
                    'Anlegen der vorhandenen Spalten im Array
                    _columns = Array.CreateInstance(GetType(System.ComponentModel.PropertyDescriptor), data.GetUpperBound(1) + 1)
                    For columnIndex As Integer = 1 To data.GetUpperBound(1)
                        _columns(columnIndex) = New PropertyDescriptor(columnIndex)
                    Next
            Da kommt erstmal keine Fehler mehr.

            Nun bekomme ich an dieser Stelle beim 2. Aufruf "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt"
            Code:
            Public Function GetItemProperties(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ITypedList.GetItemProperties
                    Return New System.ComponentModel.PropertyDescriptorCollection(_columns)
                End Function

            Kannst Du mir nochmal auf die Sprünge helfen?

            Comment


            • #7
              Das lag an der "alten" Form des Konstruktors der Klasse Table: hier war irrtümlich von einem Array ausgegangen worden, das in beiden Dimensionen null-indiziert ist. In der aktuellen Form des Codes wird mit GetLowerBound() sowohl für die Zeilen als auch für die Spalten gearbeitet.
              Beheben der Exception: den Konstruktor nochmals übernehmen.

              Comment


              • #8
                Danke! Funktioniert jetzt super!

                Comment


                • #9
                  Na dann puuh.. aufatmen

                  Comment

                  Working...
                  X