Results 1 to 8 of 8

Thread: [RESOLVED] [2008] Copying state of Treeview

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Resolved [RESOLVED] [2008] Copying state of Treeview

    Hi,

    I have one main form with a panel called pnl. On the panel are a few controls including a Treeview (tv1).

    Now, when the user clicks a certain button, the panel pnl (including the treeview) is hidden, and a new form opens, showing the same treeview.
    (Basically, you could see it as 'undocking' the treeview from the main form into a seperate form)

    Now, I want the treeview in the new seperate form to have the same state (that is, the same nodes opened) as the treeview I have just hidden.


    I tried this code but for some reason it is not working:

    In the main form, in the 'undock' button click event:
    vb.net Code:
    1. If frmSCP.Created = True Then
    2.       frmSCP.Visible = True
    3. Else
    4.       frmSCP.Show()
    5. End If
    6. pnl.Visible = False
    (frmSCP is the seperate treeview form)

    I check for the creation of frmSCP first because loading the contents of the treeview takes a little time and I don't want it to load it all over again each time the form is loaded. Therefore I simply hide it (Visible = False) and re-show it (Visible = True) again if it was opened before.


    In frmSCP I have the following code:
    vb.net Code:
    1. Private Sub btnDock_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDock.Click
    2.         frmMain.pnl.Visible = True
    3.         frmMain.tv1.CollapseAll()
    4.         frmMain.tv1.SelectedNode = tv1.SelectedNode
    5.         Me.Visible = False
    6.     End Sub
    7.  
    8.     Private Sub frmSCP_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
    9.         tv1.CollapseAll()
    10.         tv1.SelectedNode = frmMain.tv1.SelectedNode
    11.     End Sub
    12.  
    13.     Private Sub frmSCP_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    14.         LoadTreeViewFromXmlFile(My.Resources.IntelXML, tv1)
    15.         tv1.CollapseAll()
    16.         tv1.SelectedNode = frmMain.tv1.SelectedNode
    17.     End Sub

    (LoadTreeViewFromXlmFile() is the treeview loading sub)

    As you can see, when the Dock button is pressed, the first thing to happen is to re-show the treeview in the main form. Then, all it's nodes are collapsed. Then, it's SelectedNode property is set to the same SelectedNode property of the treeview in the current form, and finally, the current form is hidden.

    When the form is activated or loaded, the treeviews nodes are all collapsed and then the correct node should be selected again.

    I know that this will not automatically expand the same nodes as the other treeview, it merely selects the same nodes (but, afaik, if you tell it to select a subnode for example, the parent node will automatically expand, no??)

    I am still looking for how to expand the same nodes...


    But first, the code above is NOT working! It does not select the same node (not even when I have a parent node selected). I can see no reason why it shouldn't be working... Also note that I have made sure that the new treeview's nodes are first selected, before closing (hiding) the old treeview, so that should give me no problems right??


    If anyone has any ideas, please let me know! Thanks.

  2. #2

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Copying state of Treeview

    Thanks, that helped alot!

    I have now succesfully been able to copy the treeview, including which nodes are expanded.

    However, the selected node is not copied over yet. If I selected some child node and then 'undock' the treeview (which copies over the treeview) then in the new treeview, the node is not selected (no nodes are).

    Is this because, as soon as I press the button, the node goes unselected (because the treeview loses focus) ? How could I do this?

  4. #4
    PowerPoster Deepak Sakpal's Avatar
    Join Date
    Mar 2002
    Location
    Mumbai, India
    Posts
    2,424

    Re: [2008] Copying state of Treeview

    Quote Originally Posted by NickThissen
    However, the selected node is not copied over yet. If I selected some child node and then 'undock' the treeview (which copies over the treeview) then in the new treeview, the node is not selected (no nodes are).

    Is this because, as soon as I press the button, the node goes unselected (because the treeview loses focus) ? How could I do this?
    No, I don't think so... because even the treeview is loosing the focus, the selected node is still there as selected. Can you post your serialization code so that people here can look into it...

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Copying state of Treeview

    I am using exactly this:
    http://www.codeproject.com/KB/vb/Tre...ataAccess.aspx

    As far as I can understand the code there seems to be no SelectedNode that gets saved and/or loaded. I have tried to add it myself but I only understand the code partially so I had no succes with that...

    I am now trying to use variations on my very first attempt (thought it might work now that the expanded nodes are the same, but don't have much hope...)


    EDIT
    I've tried to identify what is happening with my first attempt by walking through the code in debug mode. However, when hovering the mouse over "frmMain.tv1.SelectedNode" in frmSCP, there is no pop-up telling me what it contains.
    When I pass the line "Me.tv1.SelectedNode = frmMain.tv1.SelectedNode" I can see that before and after this is executed, 'Me.tv1.SelectedNode' is always Nothing, so frmMain.tv1.SelectedNode was also Nothing...??
    Last edited by NickThissen; Jun 8th, 2008 at 12:35 PM.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Copying state of Treeview

    Well I'm really stumped now...

    I made a public variable 'SelectedNode' (of type 'Treenode'). Before hiding the original treeview, I save the currently selected node to SelectedNode (debugging confirms that it is saved properly).

    Then after loading the new form (and treeview) I set the new treeview's SelectedNode property to SelectedNode:
    Me.tv1.SelectedNode = SelectedNode

    While debugging I can see that 'SelectedNode' contains (for example): {Text = 'node text'}.

    However, after stepping over the line mentioned above, Me.tv1.SelectedNode is still Nothing..?! It is simply not doing what it is supposed to do... It is not setting the value for some reason...??


    EDIT
    I made a quick test project with simply two treeviews, with the same number of nodes and childnodes.
    I then expand a parent node in both treeviews (the same parent node in both) and select one childnode.
    Then when I use the following code, it should 'carry over' the selection from tv1 to tv2, but it does not!
    Code:
            tv2.SelectedNode = tv1.SelectedNode
            tv2.Focus()
    Even though tv1.SelectedNode does have a value, tv2.SelectedNode is not set to that value...
    Last edited by NickThissen; Jun 8th, 2008 at 02:32 PM.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Copying state of Treeview

    Sorry for triple-posting, but I think it's better to post this in a seperate reply.

    I have finally made some progress, by editing the serialization process from this site:
    http://www.codeproject.com/KB/vb/Tre...ataAccess.aspx

    In the '<Serializable()> Public Structure TreeNodeData' I have added a 'Public Selected As Boolean' variable alongside the 'Checked', 'Expanded' etc variables.

    Then, in the 'Public Sub New(ByVal node As TreeNode)' sub, I have added the following line:
    'Me.Selected = node.IsSelected'
    to save the selected state of the nodes.

    Opening the xml file manually I can see that the correct node gets a 'Selected' tag with value True, while all others get False. <-- correct.

    Then I needed to find a way to read this tag and select the right node. I did this by editing the 'PopulateTree' sub slightly:
    vb.net Code:
    1. Public Sub PopulateTree(ByVal treeview As TreeView)
    2.             'Check to see if there are any root nodes in the TreeViewData
    3.             If Me.Nodes Is Nothing OrElse Me.Nodes.Length = 0 Then Exit Sub
    4.  
    5.             'Populate the TreeView with child nodes
    6.             treeview.BeginUpdate()
    7.             Dim n As Integer
    8.             For i As Integer = 0 To Me.Nodes.Length - 1
    9.                 treeview.Nodes.Add(Me.Nodes(i).ToTreeNode)
    10.  
    11.                 '--------
    12.                 If Me.Nodes(i).Selected = True Then n = i
    13.                 '--------
    14.             Next
    15.             treeview.EndUpdate()
    16.  
    17.             '--------
    18.             If n > -1 Then treeview.SelectedNode = treeview.Nodes(n)
    19.             '--------
    20.         End Sub

    (Additions are between dashed comments --------.)


    Although this seems to work, it only works for parent nodes, it does NOT work for child nodes.

    When I select a parent node and save/load the treeview state to the other treeview, the right parent node is selected.
    When I select a childnode however, the SelectedNode becomes 'Nothing' once again (and for some reason it selects the first parent node)...


    EDIT
    I have attached the test project. It contains two treeviews. You can select a node in the first (left-most) treeview and press the button to copy over the state to the right treeview. Expanded nodes are all copied over alright, but as you can see only the selected parent nodes are copied, not the child nodes.
    (NOTE, this saves a file 'tv.xml' in your C:\ drive, change the path in Form1 if you like.)
    Attached Files Attached Files
    Last edited by NickThissen; Jun 8th, 2008 at 03:08 PM.

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Copying state of Treeview

    EDIT


    Nevermind I finally got it to work! I think it's quite a messy solution and might only work in my case (where there's only one level of childnodes).

    If anyone wants to know how I did it, I used the project from the links I posted above, and edited it slightly. The code is now this (edited bits are clearly stated):

    vb.net Code:
    1. Option Strict On
    2.  
    3. ''' <summary>
    4. ''' The TreeViewDataAccess class allows the nodes within a TreeView to be
    5. ''' persisted to xml for later retrevial.
    6. ''' </summary>
    7. Public Class TreeViewDataAccess
    8.  
    9.     '=============================
    10.     '----- START EDITED ----------
    11.     '=============================
    12.     Public Shared n As Integer
    13.     Public Shared tn As TreeNode
    14.     '=============================
    15.     '----- END EDITED ------------
    16.     '=============================
    17.  
    18. #Region "Structures"
    19.  
    20.     ''' <summary>
    21.     ''' TreeViewData structure represents the root node collection of a TreeView
    22.     ''' and provides the PopulateTreeView function to add these nodes to a specified
    23.     ''' TreeView instance.
    24.     ''' </summary>
    25.     <Serializable()> Public Structure TreeViewData
    26.  
    27.         ''' <summary>Array of TreeNodeData objects representing the root nodes in a TreeView.</summary>
    28.         Public Nodes() As TreeNodeData
    29.  
    30.         ''' <summary>
    31.         ''' Creates new instance of the TreeViewData structure based from the
    32.         ''' specified TreeView.
    33.         ''' </summary>
    34.         ''' <param name="treeview">TreeView to build the TreeViewData instance from.</param>
    35.         Public Sub New(ByVal treeview As TreeView)
    36.  
    37.             'Check to see if there are any root nodes in the TreeView
    38.             If treeview.Nodes.Count = 0 Then Exit Sub
    39.  
    40.             'Populate the Nodes array with child nodes
    41.             ReDim Nodes(treeview.Nodes.Count - 1)
    42.             For i As Integer = 0 To treeview.Nodes.Count - 1
    43.                 Nodes(i) = New TreeNodeData(treeview.Nodes(i))
    44.             Next
    45.         End Sub
    46.  
    47.         ''' <summary>
    48.         ''' Populates the specified TreeView with the current TreeViewData instance.
    49.         ''' </summary>
    50.         ''' <param name="treeview">TreeView instance to populate.</param>
    51.         Public Sub PopulateTree(ByVal treeview As TreeView)
    52.             'Check to see if there are any root nodes in the TreeViewData
    53.             If Me.Nodes Is Nothing OrElse Me.Nodes.Length = 0 Then Exit Sub
    54.  
    55.             'Populate the TreeView with child nodes
    56.             treeview.BeginUpdate()
    57.  
    58.             For i As Integer = 0 To Me.Nodes.Length - 1
    59.                 treeview.Nodes.Add(Me.Nodes(i).ToTreeNode())
    60.  
    61.                 '=============================
    62.                 '----- START EDITED ----------
    63.                 '=============================
    64.                 If Me.Nodes(i).Selected Then
    65.                     tn = Me.Nodes(i).ToTreeNode
    66.                     n = i
    67.                 End If
    68.                 '=============================
    69.                 '----- END EDITED ------------
    70.                 '=============================
    71.  
    72.             Next
    73.             treeview.EndUpdate()
    74.  
    75.             '=============================
    76.             '----- START EDITED ----------
    77.             '=============================
    78.             If tn.Level > 0 Then
    79.                 treeview.SelectedNode = tn
    80.             ElseIf n > -1 Then
    81.                 treeview.SelectedNode = treeview.Nodes(n)
    82.             End If
    83.             '=============================
    84.             '----- END EDITED ------------
    85.             '=============================
    86.         End Sub
    87.  
    88.     End Structure
    89.  
    90.     ''' <summary>
    91.     ''' TreeNodeData structure represents a TreeNode and provides the
    92.     ''' ToTreeNode function to convert the instance to a TreeNode object.
    93.     ''' </summary>
    94.     <Serializable()> Public Structure TreeNodeData
    95.  
    96.         ''' <summary>String representing the Text property of the TreeNode.</summary>
    97.         Public Text As String
    98.         ''' <summary>Integer representing the ImageIndex property of the TreeNode.</summary>
    99.         Public ImageIndex As Integer
    100.         ''' <summary>Integer representing the SelectedImageIndex property of the TreeNode.</summary>
    101.         Public SelectedImageIndex As Integer
    102.         ''' <summary>Boolean representing the Checked state of the TreeNode.</summary>
    103.         Public Checked As Boolean
    104.         ''' <summary>Boolean representing the Expanded state of the TreeNode.</summary>
    105.         Public Expanded As Boolean
    106.         ''' <summary>Object representing the Tag property of the TreeNode.</summary>
    107.         Public Tag As Object
    108.  
    109.         '=============================
    110.         '----- START EDITED ----------
    111.         '=============================
    112.         ''' <summary>Boolean representing the Selected property of the TreeNode.</summary>
    113.         Public Selected As Boolean
    114.         '=============================
    115.         '----- END EDITED ------------
    116.         '=============================
    117.  
    118.         ''' <summary>Array of TreeNodeData objects representing the root nodes in a TreeView.</summary>
    119.         Public Nodes() As TreeNodeData
    120.  
    121.         ''' <summary>
    122.         ''' Creates new instance of the TreeNodeData structure based on the specified TreeNode.
    123.         ''' </summary>
    124.         ''' <param name="node">TreeNode to build the TreeNodeData instance from.</param>
    125.         Public Sub New(ByVal node As TreeNode)
    126.             'Set the basic TreeNode properties
    127.             Me.Text = node.Text
    128.             Me.ImageIndex = node.ImageIndex
    129.             Me.SelectedImageIndex = node.SelectedImageIndex
    130.             Me.Checked = node.Checked
    131.             Me.Expanded = node.IsExpanded
    132.  
    133.             '=============================
    134.             '----- START EDITED ----------
    135.             '=============================
    136.             Me.Selected = node.IsSelected
    137.             '=============================
    138.             '----- END EDITED ------------
    139.             '=============================
    140.  
    141.             'See if there is an object in the tag property and if it is serializable
    142.             If (Not node.Tag Is Nothing) AndAlso node.Tag.GetType.IsSerializable Then Me.Tag = node.Tag
    143.  
    144.             'Check to see if there are any child nodes
    145.             If node.Nodes.Count = 0 Then Exit Sub
    146.  
    147.             'Recurse through child nodes and add to Nodes array
    148.             ReDim Nodes(node.Nodes.Count - 1)
    149.             For i As Integer = 0 To node.Nodes.Count - 1
    150.                 Nodes(i) = New TreeNodeData(node.Nodes(i))
    151.             Next
    152.         End Sub
    153.  
    154.         ''' <summary>
    155.         ''' Returns as TreeNode built from the instance of the TreeNodeData object.
    156.         ''' </summary>
    157.         Public Function ToTreeNode() As TreeNode
    158.             'Create TreeNode based on instance of TreeNodeData and set basic properties
    159.             ToTreeNode = New TreeNode(Me.Text, Me.ImageIndex, Me.SelectedImageIndex)
    160.             ToTreeNode.Checked = Me.Checked
    161.             ToTreeNode.Tag = Me.Tag
    162.             If Me.Expanded Then ToTreeNode.Expand()
    163.  
    164.             '=============================
    165.             '----- START EDITED ----------
    166.             '=============================
    167.             If Me.Selected Then tn = ToTreeNode
    168.             '=============================
    169.             '----- END EDITED ------------
    170.             '=============================
    171.  
    172.             'Recurse through child nodes adding to Nodes collection
    173.             If Me.Nodes Is Nothing OrElse Me.Nodes.Length = 0 Then Exit Function
    174.  
    175.             For i As Integer = 0 To Me.Nodes.Length - 1
    176.                 ToTreeNode.Nodes.Add(Me.Nodes(i).ToTreeNode())
    177.             Next
    178.  
    179.         End Function
    180.  
    181.     End Structure
    182.  
    183. #End Region
    184.  
    185. #Region "Public"
    186.  
    187.     ''' <summary>
    188.     ''' Populates the specified TreeView from the serialized TreeViewData structure file specified.
    189.     ''' </summary>
    190.     ''' <param name="treeView">TreeView instance to populate.</param>
    191.     ''' <param name="path">Serialized Xml representation of TreeViewData</param>
    192.     Public Shared Sub LoadTreeViewData(ByVal treeView As TreeView, ByVal path As String)
    193.         'Create as serializer and get the file to deserialize
    194.         Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(TreeViewData))
    195.         Dim file As New System.IO.FileStream(path, IO.FileMode.Open)
    196.         Dim reader As New System.Xml.XmlTextReader(file)
    197.  
    198.         'Deserialize the file and populate the treeview
    199.         Dim treeData As TreeViewData = CType(ser.Deserialize(reader), TreeViewData)
    200.         treeData.PopulateTree(treeView)
    201.  
    202.         'Tidy up
    203.         reader.Close()
    204.         file.Close()
    205.         file = Nothing
    206.     End Sub
    207.  
    208.     ''' <summary>
    209.     ''' Saves the specified TreeView in serialized TreeViewData structure file specified.
    210.     ''' </summary>
    211.     ''' <param name="treeView">TreeView instance to save.</param>
    212.     ''' <param name="path">Path to store serialized file.</param>
    213.     Public Shared Sub SaveTreeViewData(ByVal treeView As TreeView, ByVal path As String)
    214.         'Create as serializer and file to save TreeViewData
    215.         Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(TreeViewData))
    216.         Dim file As New System.IO.FileStream(path, IO.FileMode.Create)
    217.         Dim writer As New System.Xml.XmlTextWriter(file, Nothing)
    218.  
    219.         'Generate TreeViewData from TreeView and serialize the file.
    220.         ser.Serialize(writer, New TreeViewData(treeView))
    221.  
    222.         'Tidy up
    223.         writer.Close()
    224.         file.Close()
    225.         file = Nothing
    226.     End Sub
    227.  
    228. #End Region
    229.  
    230. End Class
    Last edited by NickThissen; Jun 9th, 2008 at 12:17 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width