|
Public Class DragDropPersistingTreeView
Inherits System.Windows.Forms.TreeView
''' <summary>
''' The TreeViewDataAccess class allows the nodes within a TreeView to be
''' persisted to xml for later retrevial and supports drag and drop
''' operation on nodes.
''' </summary>
#Region " Windows Form Designer generated code "
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
#End Region
#Region "Structures"
''' <summary>
''' TreeViewData structure represents the root node collection of a TreeView
''' and provides the PopulateTreeView function to add these nodes to a specified
''' TreeView instance.
''' </summary>
<Serializable()> Public Structure TreeViewData
''' <summary>Array of TreeNodeData objects representing the root nodes in a TreeView.</summary>
Public Nodes() As TreeNodeData
''' <summary>
''' Creates new instance of the TreeViewData structure based from the
''' specified TreeView.
''' </summary>
''' <param name="treeview">TreeView to build the TreeViewData instance from.</param>
Public Sub New(ByVal treeview As TreeView)
'Check to see if there are any root nodes in the TreeView
If treeview.Nodes.Count = 0 Then Exit Sub
'Populate the Nodes array with child nodes
ReDim Nodes(treeview.Nodes.Count - 1)
For i As Integer = 0 To treeview.Nodes.Count - 1
Nodes(i) = New TreeNodeData(treeview.Nodes(i))
Next
End Sub
''' <summary>
''' Populates the specified TreeView with the current TreeViewData instance.
''' </summary>
''' <param name="treeview">TreeView instance to populate.</param>
Public Sub PopulateTree(ByVal treeview As TreeView)
'Check to see if there are any root nodes in the TreeViewData
If Me.Nodes Is Nothing OrElse Me.Nodes.Length = 0 Then Exit Sub
'Clear the existing nodes from the TreeView
treeview.Nodes.Clear()
'Populate the TreeView with child nodes
treeview.BeginUpdate()
For i As Integer = 0 To Me.Nodes.Length - 1
treeview.Nodes.Add(Me.Nodes(i).ToTreeNode)
Next
treeview.EndUpdate()
End Sub
End Structure
''' <summary>
''' TreeNodeData structure represents a TreeNode and provides the
''' ToTreeNode function to convert the instance to a TreeNode object.
''' </summary>
<Serializable()> Public Structure TreeNodeData
''' <summary>String representing the Text property of the TreeNode.</summary>
Public Text As String
''' <summary>Integer representing the ImageIndex property of the TreeNode.</summary>
Public ImageIndex As Integer
''' <summary>Integer representing the SelectedImageIndex property of the TreeNode.</summary>
Public SelectedImageIndex As Integer
''' <summary>Boolean representing the Checked state of the TreeNode.</summary>
Public Checked As Boolean
''' <summary>Boolean representing the Expanded state of the TreeNode.</summary>
Public Expanded As Boolean
''' <summary>Object representing the Tag property of the TreeNode.</summary>
Public Tag As Object
''' <summary>Array of TreeNodeData objects representing the root nodes in a TreeView.</summary>
Public Nodes() As TreeNodeData
''' <summary>
''' Creates new instance of the TreeNodeData structure based on the specified TreeNode.
''' </summary>
''' <param name="node">TreeNode to build the TreeNodeData instance from.</param>
Public Sub New(ByVal node As TreeNode)
'Set the basic TreeNode properties
Me.Text = node.Text
Me.ImageIndex = node.ImageIndex
Me.SelectedImageIndex = node.SelectedImageIndex
Me.Checked = node.Checked
Me.Expanded = node.IsExpanded
'See if there is an object in the tag property and if it is serializable
If (Not node.Tag Is Nothing) AndAlso node.Tag.GetType.IsSerializable Then Me.Tag = node.Tag
'Check to see if there are any child nodes
If node.Nodes.Count = 0 Then Exit Sub
'Recurse through child nodes and add to Nodes array
ReDim Nodes(node.Nodes.Count - 1)
For i As Integer = 0 To node.Nodes.Count - 1
Nodes(i) = New TreeNodeData(node.Nodes(i))
Next
End Sub
''' <summary>
''' Returns as TreeNode built from the instance of the TreeNodeData object.
''' </summary>
Public Function ToTreeNode() As TreeNode
'Create TreeNode based on instance of TreeNodeData and set basic properties
ToTreeNode = New TreeNode(Me.Text, Me.ImageIndex, Me.SelectedImageIndex)
ToTreeNode.Checked = Me.Checked
ToTreeNode.Tag = Me.Tag
If Me.Expanded Then ToTreeNode.Expand()
'Recurse through child nodes adding to Nodes collection
If Me.Nodes Is Nothing OrElse Me.Nodes.Length = 0 Then Exit Function
For i As Integer = 0 To Me.Nodes.Length - 1
ToTreeNode.Nodes.Add(Me.Nodes(i).ToTreeNode)
Next
End Function
End Structure
#End Region
#Region "Constructors"
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Me.AllowDrop = True
End Sub
#End Region
#Region "Public"
''' <summary>
''' Populates the DragDropPersistingTreeView from the serialized TreeViewData structure file specified.
''' </summary>
''' <param name="path">Serialized Xml representation of TreeViewData</param>
Public Sub LoadFromXml(ByVal path As String)
'Create as serializer and get the file to deserialize
Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(TreeViewData))
Dim file As New System.IO.FileStream(path, IO.FileMode.Open)
Dim reader As New System.Xml.XmlTextReader(file)
'Deserialize the file and populate the treeview
Dim treeData As TreeViewData = CType(ser.Deserialize(reader), TreeViewData)
treeData.PopulateTree(Me)
'Tidy up
reader.Close()
file.Close()
file = Nothing
End Sub
''' <summary>
''' Saves the DragDropPersistingTreeView in serialized TreeViewData structure file specified.
''' </summary>
''' <param name="path">Path to store serialized file.</param>
Public Sub SaveToXml(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)
'Generate TreeViewData from DragDropPersistingTreeView and serialize the file.
ser.Serialize(writer, New TreeViewData(Me))
'Tidy up
writer.Close()
file.Close()
file = Nothing
End Sub
#End Region
#Region "Protected"
Protected Overrides Sub OnItemDrag(ByVal e As System.Windows.Forms.ItemDragEventArgs)
'Ensure the base method is called
MyBase.OnItemDrag(e)
'Set the drag node and initiate the DragDrop
DoDragDrop(e.Item, DragDropEffects.Move)
End Sub
Protected Overrides Sub OnDragEnter(ByVal e As System.Windows.Forms.DragEventArgs)
'Ensure the base method is called
MyBase.OnDragEnter(e)
'See if there is a TreeNode being dragged
If e.Data.GetDataPresent("System.Windows.Forms.TreeNode", True) Then
'TreeNode found allow move effect
e.Effect = DragDropEffects.Move
Else
'No TreeNode found, prevent move
e.Effect = DragDropEffects.None
End If
End Sub
Protected Overrides Sub OnDragOver(ByVal e As DragEventArgs)
'Ensure the base method is called
MyBase.OnDragOver(e)
'Check that there is a TreeNode being dragged
If e.Data.GetDataPresent("System.Windows.Forms.TreeNode", True) = False Then Exit Sub
'As the mouse moves over nodes, provide feedback to the user
'by highlighting the node that is the current drop target
Dim pt As Point = PointToClient(New Point(e.X, e.Y))
Dim targetNode As TreeNode = GetNodeAt(pt)
'See if the targetNode is currently selected, if so no need to validate again
If Not (SelectedNode Is targetNode) Then
'Select the node currently under the cursor
SelectedNode = targetNode
'Check that the selected node is not the dropNode and also that it
'is not a child of the dropNode and therefore an invalid target
Dim dropNode As TreeNode = CType(e.Data.GetData("System.Windows.Forms.TreeNode"), TreeNode)
Do Until targetNode Is Nothing
If targetNode Is dropNode Then
e.Effect = DragDropEffects.None
Exit Sub
End If
targetNode = targetNode.Parent
Loop
End If
'Currently selected node is a suitable target, allow the move
e.Effect = DragDropEffects.Move
End Sub
Protected Overrides Sub OnDragDrop(ByVal e As System.Windows.Forms.DragEventArgs)
'Ensure the base method is called
MyBase.OnDragDrop(e)
'Check that there is a TreeNode being dragged
If e.Data.GetDataPresent("System.Windows.Forms.TreeNode", True) = False Then Exit Sub
'Get the TreeNode being dragged
Dim dropNode As TreeNode = CType(e.Data.GetData("System.Windows.Forms.TreeNode"), TreeNode)
'The target node should be selected from the DragOver event
Dim targetNode As TreeNode = SelectedNode
'Remove the drop node from its current location
dropNode.Remove()
'If there is no targetNode add dropNode to the bottom of the TreeView root
'nodes, otherwise add it to the end of the dropNode child nodes
If targetNode Is Nothing Then
Nodes.Add(dropNode)
Else
targetNode.Nodes.Add(dropNode)
End If
'Ensure the newley created node is visible to the user and select it
dropNode.EnsureVisible()
SelectedNode = dropNode
End Sub
'UserControl overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
#End Region
End Class
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.