I'm trying to create a VB Application with a tree view that can be added to and edited as needed on a daily basis..
So far, I have a form that contains a Tree view control, text boxes and command buttons for Adding, Renaming and Deleting Tree Nodes.
Currently, I can add a new node without problem BUT but...if I exit or quit the application and then re-launch the application, any changes made are gone.
The idea of an XML file was suggested to store and save the changes.
If I do create an XML file, how to I call it, add to it, and edit it, so that changes are stored locally in a folder?
Regards,
Kelly
Last edited by kellman; Sep 17th, 2012 at 08:30 PM.
You have to create the saving function yourself using whatever method you feel is necessary, whether that be an INI file (I don't recommend), or an XML file.
You have to create the saving function yourself using whatever method you feel is necessary, whether that be an INI file (I don't recommend), or an XML file.
Can you help me out with how to go about creating a save function for XML file?
Look into the XmlSerializer class. If you want to use an INI file instead, you can look into my ini library which will actually generate XML for you based on sections, keys, and values for you.
Look into the XmlSerializer class. If you want to use an INI file instead, you can look into my ini library which will actually generate XML for you based on sections, keys, and values for you.
Formlesstree4,
Would it be possible to have another moderator help me, or answer my question?
The web links you are giving me contain nothing that is helpful to me as a beginner.
Once you've got loading the file into a TreeView figured out we can work on adding nodes to the XDocument and saving the changes.
Okay this is what I have so far. Thought I would start off with a small "test" program first.
Code:
Imports System.Xml
Public Class Form1
Inherits Form
Public Sub New()
MyBase.New()
InitializeComponent()
BuildTree(TreeView1, XDocument.Load("c:\temp\system.xml"))
End Sub
Private Sub BuildTree(ByVal treeView As TreeView, ByVal doc As XDocument)
Dim treeNode As TreeNode = New TreeNode(doc.Root.Name.LocalName)
treeView.Nodes.Add(treeNode)
BuildNodes(treeNode, doc.Root)
End Sub
Private Sub BuildNodes(ByVal treeNode As TreeNode, ByVal element As XElement)
For Each child As XNode In element.Nodes
Select Case (child.NodeType)
Case XmlNodeType.Element
Dim childElement As XElement = CType(child, XElement)
Dim childTreeNode As TreeNode = New TreeNode(childElement.Name.LocalName)
treeNode.Nodes.Add(childTreeNode)
BuildNodes(childTreeNode, childElement)
Case XmlNodeType.Text
Dim childText As XText = CType(child, XText)
treeNode.Nodes.Add(New TreeNode(childText.Value))
End Select
Next
End Sub
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
End Sub
End Class
Next I will add command buttons. One for Adding a new node. One for Editing a node. One for deleting a node.
They're examples of adding, editing and deleting nodes in an XML document, which is what you're loading your TreeView from. Just because it's not the exact same situation doesn't mean that there isn't something to learn there and adapt to your needs.
This pattern in common to all great programmers I know: they're not experts in something as much as experts in becoming experts in something.
The best programming advice I ever got was to spend my entire career becoming educable. And I suggest you do the same.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim filePath = "C:\Temp\Users.xml"
'Load the .xml file into an XDocument object
Dim xdoc = XDocument.Load(filePath)
Dim searchUserName = "BSmith"
'Get an XElement where the UserName child node's value is "BSmith"
'FirstOrDefault means that it will return the 1st instance it finds or Nothing if it isn't found.
Dim elementByUserName = xdoc...<User>.Where(Function(n) n.<UserName>.Value = searchUserName).FirstOrDefault
'Create a new UserClass object and assign values to the properties
Dim user As New UserClass With
{
.UserName = elementByUserName.<UserName>.Value,
.Password = elementByUserName.<Password>.Value
}
'Change the password
elementByUserName.<Password>.Value = "Password2"
'Save the changes back to the .xml file
xdoc.Save(filePath)
End Sub
End Class
Public Class UserClass
Public Property UserName As String
Public Property Password As String
End Class
Problem. After I add the TreeViewDataAccess Class to my Project and point it to my "test_tree.xml" file, I get the following error message:
Full Exception Details here:
Code:
System.InvalidOperationException was unhandled
Message=There is an error in XML document (2, 2).
Source=System.Xml
StackTrace:
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
at WindowsApplication1.TreeViewDataAccess.LoadTreeViewData(TreeView treeView, String path) in C:\Users\Kelly\Documents\Visual Studio 2010\Projects\XML Treeview\XML Treeview\TreeViewDataAccess.vb:line 137
at WindowsApplication1.Form1.Button2_Click(Object sender, EventArgs e) in C:\Users\Kelly\Documents\Visual Studio 2010\Projects\XML Treeview\XML Treeview\Form1.vb:line 38
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at WindowsApplication1.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.InvalidOperationException
Message=<family xmlns=''> was not expected.
Source=wvrxzxii
StackTrace:
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderTreeViewData.Read4_TreeViewData()
InnerException:
Public Class Form1
Inherits Form
Private Sub BuildTree(ByVal treeView As TreeView, ByVal doc As XDocument)
Dim treeNode As TreeNode = New TreeNode(doc.Root.Name.LocalName)
treeView.Nodes.Add(treeNode)
BuildNodes(treeNode, doc.Root)
End Sub
Private Sub BuildNodes(ByVal treeNode As TreeNode, ByVal element As XElement)
For Each child As XNode In element.Nodes
Select Case (child.NodeType)
Case Xml.XmlNodeType.Element
Dim childElement As XElement = CType(child, XElement)
Dim childTreeNode As TreeNode = New TreeNode(childElement.Name.LocalName)
treeNode.Nodes.Add(childTreeNode)
BuildNodes(childTreeNode, childElement)
Case Xml.XmlNodeType.Text
Dim childText As XText = CType(child, XText)
treeNode.Nodes.Add(New TreeNode(childText.Value))
End Select
Next
End Sub
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TreeViewDataAccess.SaveTreeViewData(TreeView1, "d:\test_tree.xml")
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
TreeViewDataAccess.LoadTreeViewData(TreeView1, "d:\test_tree.xml")
End Sub
End Class
As far as you are going to use this class TreeViewDataAccess then you must load xml file that previously saved by it too. so, build your tree as usual, execute TreeViewDataAccess.SaveTreeViewData then on form_load execute TreeViewDataAccess.LoadTreeViewData
BTW: when i test, i found that the method SaveTreeViewData generates the XML as one line of text which make it too difficult to read or edit in text editor like Notepad, so to let it output the XML as the above sample, replace the original method with the following one
Code:
Public Shared Sub SaveTreeViewData(ByVal treeView As TreeView, ByVal path As String)
'Create as serializer and file to save TreeViewData
Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(TreeViewData))
Dim file As New System.IO.FileStream(path, IO.FileMode.Create)
Dim writer As New System.Xml.XmlTextWriter(file, Nothing)
writer.Formatting = Xml.Formatting.Indented ' ---------> Added by 4x2y
'Generate TreeViewData from TreeView and serialize the file.
ser.Serialize(writer, New TreeViewData(treeView))
'Tidy up
writer.Close()
file.Close()
file = Nothing
End Sub
[QUOTE=4x2y;4242535]As far as you are going to use this class TreeViewDataAccess then you must load xml file that previously saved by it too. so, build your tree as usual, execute TreeViewDataAccess.SaveTreeViewData then on form_load execute TreeViewDataAccess.LoadTreeViewData
Would I use something like TreeViewDataAccess.ADDTreeViewData or TreeViewDataAccess.EditTreeViewData
No, just concentrate on working with your TreeView control (adding, deleting, modifying etc...) then when you want to save just call TreeViewDataAccess.SaveTreeViewData
No, just concentrate on working with your TreeView control (adding, deleting, modifying etc...) then when you want to save just call TreeViewDataAccess.SaveTreeViewData
Fantastic...brilliant!
I've added a button to remove a selected node. Is it possible to have a "delete confirmation" Yes/No prompt? (that echo's back the name of node).
Code:
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
TreeView1.SelectedNode.Remove() ' Delete the selected node.
End Sub
I've added a button to remove a selected node. Is it possible to have a "delete confirmation" Yes/No prompt? (that echo's back the name of node).
Code:
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
TreeView1.SelectedNode.Remove() ' Delete the selected node.
End Sub
BTW: when i test, i found that the method SaveTreeViewData generates the XML as one line of text which make it too difficult to read or edit in text editor like Notepad, so to let it output the XML as the above sample, replace the original method with the following one
Code:
Public Shared Sub SaveTreeViewData(ByVal treeView As TreeView, ByVal path As String)
'Create as serializer and file to save TreeViewData
Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(TreeViewData))
Dim file As New System.IO.FileStream(path, IO.FileMode.Create)
Dim writer As New System.Xml.XmlTextWriter(file, Nothing)
writer.Formatting = Xml.Formatting.Indented ' ---------> Added by 4x2y
'Generate TreeViewData from TreeView and serialize the file.
ser.Serialize(writer, New TreeViewData(treeView))
'Tidy up
writer.Close()
file.Close()
file = Nothing
End Sub
I tried your suggestion but it contains the following errors:
Yes, just edit your treeview as you like, the method TreeViewDataAccess.SaveTreeViewData will generate the XML file to reflect the current treeview structure.
Yes, just edit your treeview as you like, the method TreeViewDataAccess.SaveTreeViewData will generate the XML file to reflect the current treeview structure.
When I load my project in VS2010 the treeview window does not display the XML tree. I was hoping to use the built-in Node Editor.
The only time the tree is visible is at run-time.
I can still use the Node Editor to manually add a new node to the tree, but that is all.
This is what my tree looks like after pressing F5.
I would like to be able to move a node up or down on the tree, similar to the vs2010 built-in node editor.
Add two buttons and call MoveTreeNodeUp/MoveTreeNodeUp from their click event
Code:
Private Sub MoveTreeNodeUp()
Dim tvnNodeToMove As TreeNode = TreeView1.SelectedNode
Dim tvnPrevNode As TreeNode = TreeView1.SelectedNode.PrevNode
If tvnPrevNode IsNot Nothing Then
TreeView1.BeginUpdate()
TreeView1.SelectedNode.Remove()
If tvnPrevNode.Parent IsNot Nothing Then
tvnPrevNode.Parent.Nodes.Insert(tvnPrevNode.Index, tvnNodeToMove)
Else
TreeView1.Nodes.Insert(tvnPrevNode.Index, tvnNodeToMove)
End If
TreeView1.SelectedNode = tvnNodeToMove
TreeView1.EndUpdate()
End If
End Sub
Private Sub MoveTreeNodeDown()
Dim tvnNodeToMove As TreeNode = TreeView1.SelectedNode
Dim tvnNextNode As TreeNode = TreeView1.SelectedNode.NextNode
If tvnNextNode IsNot Nothing Then
TreeView1.BeginUpdate()
TreeView1.SelectedNode.Remove()
If tvnNextNode.Parent IsNot Nothing Then
tvnNextNode.Parent.Nodes.Insert(tvnNextNode.Index + 1, tvnNodeToMove)
Else
TreeView1.Nodes.Insert(tvnNextNode.Index + 1, tvnNodeToMove)
End If
TreeView1.SelectedNode = tvnNodeToMove
TreeView1.EndUpdate()
End If
End Sub