在Visual Basic

时间:2015-10-30 17:02:31

标签: xml vb.net button combobox

是的,我知道与此主题相关的无数帖子;但是,我一直无法找到答案。

我正在为RPG制作角色编辑器,我需要一个组合框来从Debug文件夹中的文件加载东西。我得到了节约;装载是我得到的。

我的代表不够高,无法发布图片,所以我会尝试彻底解释。

有两个组合框和三个按钮。

第一个组合框是用户输入所需字符的名称,然后按"添加"按钮保存以供日后使用。然后,一旦用户输入了所有字符的名称,他们就按下" Save"按钮将它们保存在看起来像这样的XML文件中,例如:

<?xml version="1.0" standalone="yes"?>
<DocumentElement>
  <character>
    <name0>Banana</name0>
  </character>
  <character>
    <name1>Fruit</name1>
  </character>
  <character>
    <name2>Grapes</name2>
  </character>
  <character>
    <name3>Oranges</name3>
  </character>
  <character>
    <name4>Taco</name4>
  </character>
  <character>
    <count>5</count>
  </character>
</DocumentElement>

注意最后总会有一个&#34;字符&#34;命名为 count 。这是输入的名称数量。根据您碰巧的解决方案,这可能会或可能不会继续。我总是在寻找一种更有效的方法,所以我会发布用于保存名称的代码。

   Private Sub saveFile(ByVal filename As String)

        count = NameBox.Items.Count
        REM create xml schema
        Dim table As New DataTable("character")


        Try
            For x = 0 To count

                If x <= count - 1 Then
                    table.Columns.Add(New DataColumn("name" & x.ToString(),     
        System.Type.GetType("System.String")))
                    REM copy character data into datatable
                    Dim row As DataRow = table.NewRow()
                    row("name" & x.ToString()) = NameBox.Items.Item(x)
                    table.Rows.Add(row)
                End If

                If x = count Then
                    table.Columns.Add(New DataColumn("count", 
        System.Type.GetType("System.String")))
                    Dim row2 As DataRow = table.NewRow()
                    row2("count") = count.ToString()
                    table.Rows.Add(row2)
                End If
            Next


            table.WriteXml(filename)
            table.Dispose()


        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
  End Sub

 Private Sub SaveButton_Click(sender As System.Object, e As   
    System.EventArgs) Handles SaveButton.Click
        Save1.DefaultExt = ".char"
        Save1.Filter = "Character Data Files|*.char"
        Save1.Title = "Save Character File"
        Save1.InitialDirectory = Environment.CurrentDirectory
        Dim result As DialogResult
        result = Save1.ShowDialog(Me)
        If result <> Windows.Forms.DialogResult.OK Then Return
        g_filename = Save1.FileName
        saveFile(g_filename)

  End Sub

注意:

Save1是一个SaveFileDialog。 NameBox是第一个组合框。 SupportBox是第二个。这些是我的globals-g_filename为String,计为Integer

现在,让我们进入这个文件的实际加载。这是我尝试过的,当然我得到了臭名昭着的错误&#34;对象引用未设置为对象的实例&#34;这是一种精心设计的说法&#34;你完成了索引或其他任何事情。&#34;

我已经根据自己的知识在线尝试了各种各样的事情。我没有公布我的所有尝试,而是将其留在此处。

基本上,我想要的是在按下“加载”按钮后将文件加载到第二个组合框(SupportBox)。

count ,正如您所猜测的那样,似乎需要包含在文件中,因此循环将知道在加载文件中的所有内容时要走多远,以防止索引错误;它也是需要的,以便程序可以在没有最初加载名称的情况下工作,从而增加了计数。 “加载”按钮需要单独运行。

如何加载此文件?

提前感谢您的帮助。

编辑:

根据请求,我会在加载此文件的一次尝试上发布一些代码。

Private Sub loadName(ByVal filename As String)
    Try

        Dim doc As New XmlDocument()
        doc.Load(filename)
        Dim list As XmlNodeList = doc.GetElementsByTagName("character")

        Dim element As XmlElement = list(0)

        For x = 1 To count
            SupportBox.Items.Add(getElement("Name" & x.ToString(), element))
        Next

    Catch ex As Exception
        MessageBox.Show(ex.Message)

    End Try

End Sub

Private Function getElement(ByVal field As String, ByRef element As   
   XmlElement) As String
    Dim value As String = ""
    Try
        value = element.GetElementsByTagName(field)(0).InnerText
    Catch ex As Exception
        REM ignore error, just return empty

        MessageBox.Show(ex.Message)

    End Try
    Return value
End Function

1 个答案:

答案 0 :(得分:1)

您的对象模型非常简单,您无需使用DataTable进行XML反序列化/序列化。我总是试图避免使用DataTables,因为我发现以下方法更容易。

以下是反序列化和序列化对象的常用方法:

Private Function Deserialize(Of T)(ByVal strXML As String) As T

    Dim objXMLSerializer As New System.Xml.Serialization.XmlSerializer(GetType(T))
    Dim objStringReader As New System.IO.StringReader(strXML)

    Return objXMLSerializer.Deserialize(objStringReader)

End Function

Private Function Serialize(ByRef TargetObject As Object) As String

    Dim objXmlSerializer As New System.Xml.Serialization.XmlSerializer(TargetObject.GetType())

    Dim objStringWriter As New System.IO.StringWriter()

    objXmlSerializer.Serialize(objStringWriter, TargetObject)

    Return objStringWriter.ToString()

End Function

接下来,创建一个用于编写XML文件的方法。您会注意到它使用上面的Serialize()函数。这样的事情应该有效:

Private Sub Write()

    Dim lstCharacters As New List(Of character)

    For x = 0 To (count - 1)

        Dim objCharacter As New character
        objCharacter.name = NameBox.Items.Item(x)

        lstCharacters.Add(objCharacter)

    Next

    IO.File.WriteAllText("C:\Some\Path.xml", Serialize(lstCharacters))

End Sub 

接下来,创建一个加载XML文件的方法。这个使用上面的Deserialize()函数。看看我如何轻松地获得此方法中的计数。

Private Sub Read()

    Dim lstCharacters As List(Of character) = Deserialize(Of List(Of character))(IO.File.ReadAllText("C:\Test\TestSO1.xml"))

    Dim intCharacterCount As Integer = lstCharacters.Count

    For Each objCharacter As character In lstCharacters

        'SupportBox.Items.Add(getElement("Name" & x.ToString(), element))

    Next

End Sub 

使用此解决方案,您不再需要使用DataTable或担心Count。生成的XML将与原始解决方案不同,但由于索引不再附加在name元素上,因此更加清晰。