The following example is a partially controlled demo in that instead of a TextBox a ComboBox is used with values inline with what you asked for. If this works for you than simply replace the ComboBox for a TextBox.
Form
1 DataGridView with two columns created in the IDE
Column 1 DataProperty = Identifier
Column 2 DataProperty = Value
1 ComboBox, 1 Button
Feel free to adjust the new items indent level as per your liking.
Code:
Public Class Form1
Private Document As New XDocument
Private FileName As String = IO.Path.Combine(Application.StartupPath, "Document.xml")
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.AutoGenerateColumns = False
Document = XDocument.Load(FileName)
DataGridView1.DataSource = _
( _
From T In Document...<Item> _
Select New With _
{ .Identifier = T.@ItemID, _
.Value = T.Value.Trim _
} _
).ToDataTable
ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
ComboBox1.DataSource = (From T In Enumerable.Range(1, 20) Select "TEST" & T.ToString).ToList
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Result = (From T In Document...<Item> Where T.Value.Trim = ComboBox1.Text).FirstOrDefault
If Result IsNot Nothing Then
MessageBox.Show("Item in file already")
Else
Dim NextId As Integer = (From T In Document...<Item> Select CInt(T.@ItemID)).Max + 1
Dim NewItem = <Item ItemID=<%= NextId %>><%= ComboBox1.Text %></Item>
Document...<Items>(0).Add(NewItem)
Document.Save(FileName)
CType(DataGridView1.DataSource, DataTable).Rows.Add(New Object() {NextId, ComboBox1.Text})
End If
End Sub
End Class
Code Module for a language extension method (cannot be in a form)
Code:
<System.Diagnostics.DebuggerStepThrough()> _
<System.Runtime.CompilerServices.Extension()> _
Public Function ToDataTable(Of T)(ByVal value As IEnumerable(Of T)) As DataTable
Dim returnTable As New DataTable
Dim firstRecord = value.First
For Each pi In firstRecord.GetType.GetProperties
returnTable.Columns.Add(pi.Name, pi.GetValue(firstRecord, Nothing).GetType)
Next
For Each result In value
Dim nr = returnTable.NewRow
For Each pi In result.GetType.GetProperties
nr(pi.Name) = pi.GetValue(result, Nothing)
Next
returnTable.Rows.Add(nr)
Next
Return returnTable
End Function
XML document named Document.xml to reside in the same folder as the executable.
Code:
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Items>
<Item ItemID="1">
TEST1
</Item>
<Item ItemID="2">
TEST2
</Item>
<Item ItemID="3">
TEST3
</Item>
</Items>
</Root>