2016-08-15 14 views
0

DataGridViewとの間でXML文字列を保存して読み込もうとしています。
次のコードで私はそれを行うことができますが、列のデータ型が失われ、グリッド全体が文字列で埋められます。この状況では、書式設定と並べ替えはうまく機能しません。保存されたデータ型を持つXMLへのDataGridView

ここに表示された処理中に元のデータ型を保持するためにできることはありますか?
私の他のプロジェクトで使用できるようにするための解決策が欲しいです。

Imports System 
    Imports System.Text 
    Imports System.Xml 
    Imports System.IO 

    Public Class Form1 

     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

      dgv.Columns.Add("col0", "col0") 
      dgv.Columns(0).ValueType = Type.GetType("Integer") 
      dgv.Columns.Add("col1", "col1") 
      dgv.Columns.Add("col2", "col2") 
      dgv.Columns(2).ValueType = Type.GetType("Double") 
      dgv.Columns(2).DefaultCellStyle.Format = "N2" 

      dgv.Rows.Add({CInt("1"), "John", CDbl("0,11")}) 
      dgv.Rows.Add({CInt("2"), "Mary", CDbl("2,8")}) 
      dgv.Rows.Add({CInt("3"), "Mike", CDbl("10,125")}) 
      dgv.Rows.Add({CInt("4"), "Suzy", CDbl("2")}) 
     End Sub 

     Private Sub dgv_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles dgv.Leave 

      If dgv.Rows.Count - 1 > 0 Then 
       Dim dsa As DataSet = New DataSet() 
       dsa.DataSetName = "xdgv" 
       Dim dxs As DataTable = GetDataTableFromDGV(dgv) 
       dsa.Tables.Add(dxs) 
       ''save xml from dgv content to textbox 
       TextBox1.Text = GenerateXML(dsa) 
      End If 
     End Sub 

     Private Function GenerateXML(ByVal xds As DataSet) As String 

      Dim obj As New StringWriterUtf8() 
      Dim xmlstring As String 
      xds.WriteXml(obj, XmlWriteMode.IgnoreSchema) 
      xmlstring = obj.ToString() 

      Return xmlstring 
     End Function 

     Private Function GetDataTableFromDGV(ByVal dgv As DataGridView) As DataTable 

      Dim dt = New DataTable() 

      Dim t As Integer = 0 
      For Each column As DataGridViewColumn In dgv.Columns 
       If column.Visible Then 
        dt.Columns.Add(dgv.Columns(t).Name) 
        t += 1 
       End If 
      Next 

      Dim cellValues As Object() = New Object(dgv.Columns.Count - 1) {} 
      For Each row As DataGridViewRow In dgv.Rows 
       If Not row.IsNewRow Then 
        For i As Integer = 0 To row.Cells.Count - 1 
         cellValues(i) = If(row.Cells(i).Value Is Nothing, String.Empty, row.Cells(i).Value) 
        Next 
        dt.Rows.Add(cellValues) 
       End If 
      Next 

      Return dt 
     End Function 

     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 

      ''load xml from textbox back to dgv 
      dgv.Rows.Clear() 

      If Not String.IsNullOrEmpty(TextBox1.Text) Then 
       Try 
        Dim Stream As StringReader = New StringReader(TextBox1.Text) 
        Dim xreader As XmlTextReader = New XmlTextReader(Stream) 
        Dim ds As DataSet = New DataSet 
        ds.ReadXml(xreader) 
        For Each table As DataTable In ds.Tables 
         For Each row As DataRow In table.Rows 
          dgv.Rows.Add(row.ItemArray()) 
         Next row 
        Next table 
        ds = Nothing 
       Catch ex As Exception 
        MessageBox.Show("xmlFoo: " + ex.Message) 
       End Try 
      End If 
     End Sub 
    End Class 

    Public Class StringWriterUtf8 
     Inherits System.IO.StringWriter 
     Public Overrides ReadOnly Property Encoding() As Encoding 
      Get 
       Return Encoding.UTF8 
      End Get 
     End Property 
    End Class 

はsucessfullyこのコードを実行するために、あなたはのDataGridView =「DGV」、テキストボックス=「TextBox1テキストボックス」とボタン=「Button1を」が含まれ、その上にForm1を持つ新しいプロジェクトが必要になります。

答えて

1

あなたのためにいくつかの再作業が必要な新しい解決策があります。 DataGridviewにデータを取り込む代わりに、データテーブルにデータを取り込み、これを使用してバインディングとシリアル化を行います。

作成されているテーブルを表示し、グリッドビューにバウンディングし、そのタイプをそのままシリアル化およびデシリアライズしたコード例を示します。

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    Dim dt As New DataTable("Src") 
    dt.Columns.Add("col0", GetType(Integer)) 
    dt.Columns.Add("col1", GetType(String)) 
    dt.Columns.Add("col2", GetType(Double)) 

    dt.Rows.Add({CInt("1"), "John", CDbl("0,11")}) 
    dt.Rows.Add({CInt("2"), "Mary", CDbl("2,8")}) 
    dt.Rows.Add({CInt("3"), "Mike", CDbl("10,125")}) 
    dt.Rows.Add({CInt("4"), "Suzy", CDbl("2")}) 

    dgv.DataSource = dt 
    dgv.Columns(2).DefaultCellStyle.Format = "N2" 

    Dim file = "c:\temp\test.xml" 
    dt.WriteXml(file, XmlWriteMode.WriteSchema) 

    Dim dt2 = New DataTable 
    dt2.ReadXml(file) 

    dgv.DataSource = dt2 
End Sub 

あなたの修正GenerateXml機能:

Private Function GenerateXML(ByVal dt As DataTable) As String 
    Dim obj As New StringWriterUtf8() 
    Dim xmlstring As String 
    dt.WriteXml(obj, XmlWriteMode.WriteSchema) 
    xmlstring = obj.ToString() 
    TextBox1.Text = xmlstring 
    Return xmlstring 
End Function 

独立したスキーマ

Dim file = "c:\temp\test.xml" 
    Dim schema = "c:\temp\test.xsd" 
    dt.WriteXml(file, XmlWriteMode.IgnoreSchema) 
    dt.WriteXmlSchema(schema) 

    Dim dt2 = New DataTable 
    dt2.ReadXmlSchema(schema) 
    dt2.ReadXml(file) 
+0

フム、私はしたいが働きません正確にどのように。ファイルの代わりに文字列(テキストボックス)を使用する方法はありますか? – user1697111

+0

私はあなたのGenerateXml関数を変更して、代わりにdatatableを使用しました。この方法は、コードの量を大幅に削減する必要があります。 – FloatingKiwi

+0

はい、うまくいきます。私はちょうどファイルの代わりに文字列を使用したい。新しいGenerateXMLのこの部分はうまくいく。私はまた、正常にDataTableをクリアし、テキストボックスからリロードしてから、再度dgvにリバインドします。つまり、2つではなく1つのデータテーブルで作業するということです。どうもありがとうございました。しかし、なぜ私は適切な型のdgv列をとにかく読むことができないのだろうかと疑問に思っています。次回はそれを解決するでしょう:) – user1697111

関連する問題