0

我正在读取一个 XML 文件并将结果存储到一个 DataSet 中。该数据集包含 10 个数据表。我想将所有 DataTables 加入一个数据表并使用此表设置为 datagridview 的数据源,以便稍后将 gridview 导出到 csv 或 excel 中。目前我在单独的网格视图中显示每个数据表。我试过 datatable.merge() 但这没有用。

关于如何在单个 datagridview 中显示这 10 个数据表的任何建议?

谢谢

Imports System.Xml

公开课形式1

Public tbl0 As New DataTable
Public tbl1 As New DataTable
Public tbl2 As New DataTable
Public tbl3 As New DataTable
Public tbl4 As New DataTable
Public tbl5 As New DataTable
Public tbl6 As New DataTable
Public tbl7 As New DataTable
Public tbl8 As New DataTable
Public tbl9 As New DataTable

Public result As New DataTable


Private Sub btnreadxml_Click(sender As Object, e As EventArgs) Handles btnreadxml.Click
    Try
        Dim filePath As String
        filePath = "C:/Win/XMLReader/822396000069521.xml"

        AuthorsDataSet.ReadXml(filePath)

        tbl0 = AuthorsDataSet.Tables(0)
        tbl1 = AuthorsDataSet.Tables(1)
        tbl2 = AuthorsDataSet.Tables(2)
        tbl3 = AuthorsDataSet.Tables(3)
        tbl4 = AuthorsDataSet.Tables(4)
        tbl5 = AuthorsDataSet.Tables(5)
        tbl6 = AuthorsDataSet.Tables(6)
        tbl7 = AuthorsDataSet.Tables(7)
        tbl8 = AuthorsDataSet.Tables(8)
        tbl9 = AuthorsDataSet.Tables(9)

        DataGridView1.DataSource = tbl1
        DataGridView2.DataSource = tbl2
        DataGridView3.DataSource = tbl3
        DataGridView4.DataSource = tbl4
        DataGridView5.DataSource = tbl5
        DataGridView6.DataSource = tbl6
        DataGridView7.DataSource = tbl7
        DataGridView8.DataSource = tbl8
        DataGridView9.DataSource = tbl9


    Catch ex As Exception

    End Try
End Sub
4

1 回答 1

2

这个问题没有一个简单的答案,但你可以做一些事情来让这个问题变得更简单。以下代码基于以下数据架构。

数据架构

我们的目标是使用LINQ解决这个任务。

我们应该做的第一件事是创建反映数据模式的自定义类。

Public Class Author
    Public Property pk_author As Integer
    Public Property firstname As String
    Public Property lastname As String
End Class

Public Class Book
    Public Property pk_book As Integer
    Public Property fk_author As Integer
    Public Property title As String
End Class

Public Class Review
    Public Property pk_review As Integer
    Public Property fk_book As Integer
    Public Property [text] As String
End Class 

接下来我们需要创建两个扩展/帮助方法。(你会在这篇文章的底部找到完整的源代码。)

数据表

此函数将根据T中定义的属性将List(Of T)转换为DataTable

<Extension()>
Public Function ToDataTable(Of T)(source As List(Of T)) As DataTable

列表

此函数将根据T中定义的属性和源表包含的列将DataTable转换为List(Of T) 。

<Extension()>
Public Function ToList(Of T As {Class, New})(source As DataTable) As List(Of T)

用法

将XML文件读入DataTable

Dim [set] As DataSet = ReadXmlIntoDataSet()

将表格“转换”为列表。

Dim authors As List(Of Author) = [set].Tables("authors").ToList(Of Author)()
Dim books As List(Of Book) = [set].Tables("books").ToList(Of Book)()
Dim reviews As List(Of Review) = [set].Tables("reviews").ToList(Of Review)()

使用LINQ加入列表,然后将结果“转换”回DataTable

Dim results As DataTable = (
    From a In authors
    From b In books.Where(Function(item) ((Not a Is Nothing) AndAlso item.fk_author = a.pk_author)).DefaultIfEmpty()
    From r In reviews.Where(Function(item) ((Not b Is Nothing) AndAlso item.fk_book = b.pk_book)).DefaultIfEmpty()
    Select New With {
        .pk_author = If((Not a Is Nothing), New Integer?(a.pk_author), Nothing),
        .pk_book = If((Not b Is Nothing), New Integer?(b.pk_book), Nothing),
        .pk_review = If((Not r Is Nothing), New Integer?(r.pk_review), Nothing),
        .firstname = If((Not a Is Nothing), a.firstname, Nothing),
        .lastname = If((Not a Is Nothing), a.lastname, Nothing),
        .title = If((Not b Is Nothing), b.title, Nothing),
        .[text] = If((Not r Is Nothing), r.[text], Nothing)
    }
).ToList().ToDataTable()

申请照片

源代码

参考

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Reflection
Imports <your namespace goes here>.Extensions

作者

Public Class Author
    Public Property pk_author As Integer
    Public Property firstname As String
    Public Property lastname As String
End Class

Public Class Book
    Public Property pk_book As Integer
    Public Property fk_author As Integer
    Public Property title As String
End Class

审查

Public Class Review
    Public Property pk_review As Integer
    Public Property fk_book As Integer
    Public Property [text] As String
End Class

扩展

<Extension()>
Public Module Extensions

    <Extension()>
    Public Function ToDataTable(Of T)(source As List(Of T)) As DataTable

        Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
        Dim table As New DataTable()
        Dim descriptor As PropertyDescriptor = Nothing
        Dim column As DataColumn = Nothing
        Dim values As Object() = Nothing
        Dim length As Integer = Nothing
        Dim index As Integer = Nothing
        Dim item As T = Nothing
        Dim type As Type = Nothing

        table.BeginInit()

        For Each descriptor In properties
            type = Nullable.GetUnderlyingType(descriptor.PropertyType)
            column = New DataColumn()
            column.ColumnName = descriptor.Name
            column.Caption = descriptor.DisplayName
            column.DataType = If((type Is Nothing), descriptor.PropertyType, type)
            column.ReadOnly = descriptor.IsReadOnly
            table.Columns.Add(column)
        Next

        table.BeginLoadData()
        length = (properties.Count - 1)
        values = New Object(length) {}

        For Each item In source
            For index = 0 To length
                values(index) = properties(index).GetValue(item)
            Next
            table.Rows.Add(values)
        Next

        table.EndLoadData()
        table.EndInit()

        Return table

    End Function

    <Extension()>
    Public Function ToList(Of T As {Class, New})(source As DataTable) As List(Of T)

        If (source Is Nothing) Then
            Throw New ArgumentNullException("source")
        End If

        Dim list As New List(Of T)
        Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
        Dim descriptor As PropertyDescriptor = Nothing
        Dim index As Integer = Nothing
        Dim row As DataRow = Nothing
        Dim item As T = Nothing

        For index = (properties.Count - 1) To 0 Step -1
            If (Not source.Columns.Contains(properties(index).Name)) Then
                properties.RemoveAt(index)
            End If
        Next

        For Each row In source.Rows
            item = New T()
            For Each descriptor In properties
                descriptor.SetValue(item, row.Item(descriptor.Name))
            Next
            list.Add(item)
        Next

        Return list

    End Function

End Module

示例应用程序

Public Class Form1

    Public Sub New()
        Me.InitializeControls()
        Try

            Dim [set] As DataSet = Form1.ReadXmlIntoDataSet()
            Dim authors As List(Of Author) = [set].Tables("authors").ToList(Of Author)()
            Dim books As List(Of Book) = [set].Tables("books").ToList(Of Book)()
            Dim reviews As List(Of Review) = [set].Tables("reviews").ToList(Of Review)()

            Dim results As DataTable = (
                From a In authors
                From b In books.Where(Function(item) ((Not a Is Nothing) AndAlso item.fk_author = a.pk_author)).DefaultIfEmpty()
                From r In reviews.Where(Function(item) ((Not b Is Nothing) AndAlso item.fk_book = b.pk_book)).DefaultIfEmpty()
                Select New With {
                    .pk_author = If((Not a Is Nothing), New Integer?(a.pk_author), Nothing),
                    .pk_book = If((Not b Is Nothing), New Integer?(b.pk_book), Nothing),
                    .pk_review = If((Not r Is Nothing), New Integer?(r.pk_review), Nothing),
                    .firstname = If((Not a Is Nothing), a.firstname, Nothing),
                    .lastname = If((Not a Is Nothing), a.lastname, Nothing),
                    .title = If((Not b Is Nothing), b.title, Nothing),
                    .[text] = If((Not r Is Nothing), r.[text], Nothing)
                }
            ).ToList().ToDataTable()

            Me.resultsGrid.DataSource = results
            Me.authorsGrid.DataSource = authors
            Me.booksGrid.DataSource = books
            Me.reviewsGrid.DataSource = reviews

        Catch ex As Exception
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub InitializeControls()
        Me.Label1 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 213), .Name = "Label1", .Size = New System.Drawing.Size(60, 18), .TabIndex = 0, .Text = "Reviews"}
        Me.Label2 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 142), .Name = "Label2", .Size = New System.Drawing.Size(45, 18), .TabIndex = 4, .Text = "Books"}
        Me.Label3 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 71), .Name = "Label3", .Size = New System.Drawing.Size(57, 18), .TabIndex = 7, .Text = "Authors"}
        Me.Label4 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Font = New System.Drawing.Font("Calibri", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte)), .Location = New System.Drawing.Point(0, 0), .Name = "Label4", .Size = New System.Drawing.Size(51, 18), .TabIndex = 10, .Text = "Result:"}
        Me.Splitter1 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 203), .Name = "Splitter1", .Size = New System.Drawing.Size(613, 10), .TabIndex = 2, .TabStop = False}
        Me.Splitter2 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 132), .Name = "Splitter2", .Size = New System.Drawing.Size(613, 10), .TabIndex = 5, .TabStop = False}
        Me.Splitter3 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 61), .Name = "Splitter3", .Size = New System.Drawing.Size(613, 10), .TabIndex = 8, .TabStop = False}
        Me.resultsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 18), .Name = "resultsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 280), .TabIndex = 9}
        Me.authorsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 89), .Name = "authorsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 115), .TabIndex = 6}
        Me.booksGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 160), .Name = "booksGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 200), .TabIndex = 3}
        Me.reviewsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Fill, .Location = New System.Drawing.Point(0, 231), .Name = "reviewsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 415), .TabIndex = 1}
        Me.SuspendLayout()
        Me.AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 18.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(613, 900)
        Me.Controls.AddRange({Me.reviewsGrid, Me.Label1, Me.Splitter1, Me.booksGrid, Me.Label2, Me.Splitter2, Me.authorsGrid, Me.Label3, Me.Splitter3, Me.resultsGrid, Me.Label4})
        Me.Font = New System.Drawing.Font("Calibri", 9.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Margin = New System.Windows.Forms.Padding(3, 4, 3, 4)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
        Me.PerformLayout()
    End Sub

    Private Shared Function ReadXmlIntoDataSet() As DataSet

        Dim [set] As New DataSet()

        Dim authors As DataTable = [set].Tables.Add("authors")

        With authors
            .Columns.Add("pk_author", GetType(Integer))
            .Columns.Add("firstname", GetType(String))
            .Columns.Add("lastname", GetType(String))
            .BeginLoadData()
            .Rows.Add(1, "William", "Shakespeare")
            .Rows.Add(2, "Henrik", "Ibsen")
            .Rows.Add(3, "Ernest", "Hemingway")
            .EndLoadData()
            .AcceptChanges()
        End With

        Dim books As DataTable = [set].Tables.Add("books")

        With books
            .Columns.Add("pk_book", GetType(Integer))
            .Columns.Add("fk_author", GetType(Integer))
            .Columns.Add("title", GetType(String))
            .BeginLoadData()
            .Rows.Add(1, 1, "Timon of Athens")
            .Rows.Add(2, 1, "Titus Othello")
            .Rows.Add(3, 1, "The Comedy of Errors")
            .Rows.Add(4, 2, "Peer Gynt")
            .Rows.Add(5, 2, "A Doll's House")
            .Rows.Add(6, 2, "Emperor and Galilean")
            .EndLoadData()
            .AcceptChanges()
        End With

        Dim reviews As DataTable = [set].Tables.Add("reviews")

        With reviews
            .Columns.Add("pk_review", GetType(Integer))
            .Columns.Add("fk_book", GetType(Integer))
            .Columns.Add("text", GetType(String))
            .BeginLoadData()
            .Rows.Add(1, 1, "The book 'Timon of Athens' blabla ...")
            .Rows.Add(2, 2, "The book 'Titus Othello' blabla ...")
            .Rows.Add(3, 4, "The book 'Peer Gynt' blabla 1...")
            .Rows.Add(4, 4, "The book 'Peer Gynt' blabla 2...")
            .Rows.Add(5, 4, "The book 'Peer Gynt' blabla 3...")
            .Rows.Add(6, 5, "The book 'A Doll's House' blabla ...")
            .EndLoadData()
            .AcceptChanges()
        End With

        [set].Relations.Add(New DataRelation("books_author", authors.Columns("pk_author"), books.Columns("fk_author")))
        [set].Relations.Add(New DataRelation("reviews_books", books.Columns("pk_book"), reviews.Columns("fk_book")))

        Return [set]

    End Function

    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents Label3 As System.Windows.Forms.Label
    Friend WithEvents Label4 As System.Windows.Forms.Label
    Friend WithEvents Splitter1 As System.Windows.Forms.Splitter
    Friend WithEvents Splitter2 As System.Windows.Forms.Splitter
    Friend WithEvents Splitter3 As System.Windows.Forms.Splitter
    Friend WithEvents resultsGrid As System.Windows.Forms.DataGridView
    Friend WithEvents authorsGrid As System.Windows.Forms.DataGridView
    Friend WithEvents booksGrid As System.Windows.Forms.DataGridView
    Friend WithEvents reviewsGrid As System.Windows.Forms.DataGridView

End Class
于 2014-05-18T15:00:43.513 回答