vb.net - Deep copy a CUSTOM treenode
问题描述
I am researching for some days now how to shallow copy and deep copy a custom TreeNode object that was dragged from treeview1 and Dropped to Treeview2. I need both behaviors in my application. I can create the custom TreeNode and have the custom properties populated from SQL Database. The main idea is to have all product options in the Treeview1 and build my product in the Treeview2.
What I can do...
1)Populate Treeview1 from SQL Database
2)Create the CUSTOM TreeNode with my properties
3)DragItem, DragEnter, DragOver and DragDrop my Custom TreeNode
What is my problem?
When I DragDrop the CUSTOM TreeNode from TreeView1 and I Add the TreeNode in the TreeView2 I need to remove the TreeNode from TreeView1 But I Would like to have the CUSTOM TreeNode on Both places TreeView1 and TreeView2.
I did a lot of research but I believe I need some guidance from you colleagues to accomplish my gol. I tried a lot of things also without success...This is the code I have that supposed to do a DeepCopy from my CUSTOM TreeNode. The concept for the DeepCopy function I took from Microsoft documentation regarding CLONE (Shallow and DeepCopy). Here is my code.
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Public Class Frm_USER_HDAS
Private Sub Frm_USER_HDAS_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView1.Nodes.Clear()
TreeView1.Nodes.Add("Nodes_Collection")
TreeView1.Nodes(0).Text = "Nodes_Collection"
Try
Call DBOpenConnection()
Dim CurrentTableName As String = "Customers"
Dim NewNode As HDAS_TreeNode
Dim DTProperties As New DataTable
Dim returnProperties As String = DB.SQLQuery("SELECT * FROM [" + CurrentTableName + "]", DTProperties)
For j As Integer = 0 To DTProperties.Rows.Count - 1
For k As Integer = 0 To DTProperties.Columns.Count - 1
If DTProperties.Columns(k).ColumnName = "Name" Then
Dim DT_ItemProperties As New DataTable
Dim retorn_DT_ItemProperties As String = DB.SQLQuery("SELECT *
FROM [" + CurrentTableName + "]
WHERE Name = '" + DTProperties.Rows(j).Item(k) + "';",
DT_ItemProperties)
Dim DTLinks As New DataTable
Dim ReturnLinks As String = DB.SQLQuery("SELECT
c.CONSTRAINT_NAME,
cu.TABLE_NAME AS ReferencingTable,
cu.COLUMN_NAME AS ReferencingColumn,
ku.TABLE_NAME AS ReferencedTable,
ku.COLUMN_NAME AS ReferencedColumn
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu
ON cu.CONSTRAINT_NAME = c.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku
ON ku.CONSTRAINT_NAME = c.UNIQUE_CONSTRAINT_NAME
WHERE ku.TABLE_NAME = '" + CurrentTableName + "'", DTLinks)
NewNode = New HDAS_TreeNode(DTLinks, DT_ItemProperties)
TreeView1.Nodes(0).Nodes.Add(NewNode)
Exit For
End If
Next
Next
TreeView1.ExpandAll()
DB.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
#Region "Drag and Drop Process"
#Region "Started Step 1"
Private Sub TreeView1_ItemDrag(sender As Object, e As ItemDragEventArgs) Handles TreeView1.ItemDrag, TreeView2.ItemDrag
sender.DoDragDrop(e.Item, DragDropEffects.Copy)
End Sub
#End Region
#Region "Started Step 2"
Private Sub TreeView1_DragEnter(sender As Object, e As DragEventArgs) Handles TreeView1.DragEnter, TreeView2.DragEnter
e.Effect = e.AllowedEffect
End Sub
#End Region
#Region "Started Step 3"
Private Sub TreeView_DragOver(sender As Object, e As DragEventArgs) Handles TreeView1.DragOver, TreeView2.DragOver
' Retrieve the client coordinates of the mouse position.
Dim targetPoint As Point = sender.PointToClient(New Point(e.X, e.Y))
' Select the node at the mouse position.
sender.SelectedNode = sender.GetNodeAt(targetPoint)
End Sub
#End Region
#Region "Started Step 4"
Private Sub TreeView_DragDrop(sender As Object, e As DragEventArgs) Handles TreeView1.DragDrop, TreeView2.DragDrop
Dim selectedTreeview As TreeView
selectedTreeview = CType(sender, TreeView)
' Retrieve the client coordinates of the drop location.
Dim targetPoint As Point = sender.PointToClient(New Point(e.X, e.Y))
' Retrieve the node at the drop location.
Dim targetNode As HDAS_TreeNode = sender.GetNodeAt(targetPoint)
' Retrieve the node that was dragged.
Dim draggedNode As HDAS_TreeNode = CType(e.Data.GetData(GetType(HDAS_TreeNode)), HDAS_TreeNode)
Dim DroppedNode As HDAS_TreeNode = draggedNode
If Not draggedNode.Equals(targetNode) AndAlso Not ContainsNode(draggedNode, targetNode) Then
If targetNode Is Nothing Then
draggedNode.Remove() 'The Problem is here....If I remove this line I can not Keep Both Nodes
selectedTreeview.Nodes.Add(DroppedNode.DeepCopy())
Else
draggedNode.Remove() 'The Problem is here....If I remove this line I can not Keep Both Nodes
targetNode.Nodes.Add(DroppedNode.DeepCopy())
End If
draggedNode.EnsureVisible()
selectedTreeview.SelectedNode = draggedNode
sender.ExpandAll()
End If
End Sub
Private Function ContainsNode(ByVal node1 As HDAS_TreeNode, ByVal node2 As HDAS_TreeNode) As Boolean
Try
' Check the parent node of the second node.
If node2.Parent Is Nothing Then
Return False
End If
If node2.Parent.Equals(node1) Then
Return True
End If
' If the parent node is not null or equal to the first node,
' call the ContainsNode method recursively using the parent of
' the second node.
Return ContainsNode(node1, node2.Parent)
Catch ex As Exception
End Try
End Function 'ContainsNode
#End region
#Region"Here is my CUSTOM TreeNode Class"
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable> Public Class HDAS_TreeNode
Inherits TreeNode
Private NodeName As String
Private NodeText As String
Private CurrentTableName As String
Private CurrentTablePrimaryKeys As List(Of String)
Private LinkedTableNames As List(Of String)
Private LinkedTableForeignerKeys As List(Of String)
Private PropertiesFromDB As DataTable
Private M_DTLinks As New DataTable
Private M_DTProperties As New DataTable
#Region "Constructor"
Public Sub New()
End Sub
Sub New(DTLinks As DataTable, DTProperties As DataTable)
M_DTLinks = DTLinks
M_DTProperties = DTProperties
Me.Name = HDAS_NodeName
Me.Text = HDAS_NodeText
Me.CurrentTableName = HDAS_CurrentTable
Me.CurrentTablePrimaryKeys = HDAS_PrimaryKeys
Me.LinkedTableNames = HDAS_LinkedTables
Me.LinkedTableForeignerKeys = HDAS_ForeignerKeys
Me.PropertiesFromDB = HDAS_PropertiesFromDB
End Sub
#End Region
#Region "Properties"
Public Property HDAS_NodeName As String
Get
Return MyNodeName(M_DTProperties)
End Get
Set(value As String)
NodeName = value
End Set
End Property
Public Property HDAS_NodeText As String
Get
Return MyNodeText(M_DTProperties)
End Get
Set(value As String)
NodeText = value
End Set
End Property
Public Property HDAS_CurrentTable As String
Get
Return MyNodeCurrentTable(M_DTLinks)
End Get
Set(value As String)
CurrentTableName = value
End Set
End Property
Public Property HDAS_PrimaryKeys As List(Of String)
Get
Return MyNodePrimaryKeys(M_DTLinks)
End Get
Set(value As List(Of String))
CurrentTablePrimaryKeys = value
End Set
End Property
Public Property HDAS_LinkedTables As List(Of String)
Get
Return MyNodeLinkedTableName(M_DTLinks)
End Get
Set(value As List(Of String))
LinkedTableNames = value
End Set
End Property
Public Property HDAS_ForeignerKeys As List(Of String)
Get
Return MyNodeForeignerKeys(M_DTLinks)
End Get
Set(value As List(Of String))
LinkedTableForeignerKeys = value
End Set
End Property
Public Property HDAS_PropertiesFromDB As DataTable
Get
Return M_DTProperties
End Get
Set(value As DataTable)
PropertiesFromDB = value
End Set
End Property
#End Region
#Region "Methods"
Private Function MyNodeName(DTProperties As DataTable) As String
Try
For i As Integer = 0 To DTProperties.Columns.Count
If DTProperties.Columns(i).ColumnName = "Name" Then
MyNodeName = DTProperties.Rows(0).Item(i)
Return MyNodeName
End If
Next
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodeName" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Private Function MyNodeText(DTProperties As DataTable) As String
Try
For i As Integer = 0 To DTProperties.Columns.Count
If DTProperties.Columns(i).ColumnName = "Name" Then
MyNodeText = DTProperties.Rows(0).Item(i)
Return MyNodeText
End If
Next
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodeText" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Private Function MyNodeCurrentTable(M_DTLinks As DataTable) As String
Try
MyNodeCurrentTable = M_DTLinks.Rows(0).Item(3)
Return MyNodeCurrentTable
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodeCurrentTable" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Private Function MyNodePrimaryKeys(M_DTLinks As DataTable) As List(Of String)
Try
Dim LinkedTableList As List(Of String) = Nothing
MyNodePrimaryKeys = Nothing
If M_DTLinks.Rows.Count > 1 Then
LinkedTableList = New List(Of String)
For i As Integer = 0 To M_DTLinks.Rows.Count - 1
Dim LinkedTableName As String = M_DTLinks.Rows(i).Item(4)
LinkedTableList.Add(LinkedTableName)
Next
MyNodePrimaryKeys = LinkedTableList
Return MyNodePrimaryKeys
Else
MyNodePrimaryKeys = M_DTLinks.Rows(0).Item(4)
Return MyNodePrimaryKeys
End If
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodePrimaryKeys" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Private Function MyNodeLinkedTableName(M_DTLinks As DataTable) As List(Of String)
Try
Dim LinkedTableList As List(Of String) = Nothing
MyNodeLinkedTableName = Nothing
If M_DTLinks.Rows.Count > 1 Then
LinkedTableList = New List(Of String)
For i As Integer = 0 To M_DTLinks.Rows.Count - 1
Dim LinkedTableName As String = M_DTLinks.Rows(i).Item(1)
LinkedTableList.Add(LinkedTableName)
Next
MyNodeLinkedTableName = LinkedTableList
Return MyNodeLinkedTableName
Else
MyNodeLinkedTableName = M_DTLinks.Rows(0).Item(1)
Return MyNodeLinkedTableName
End If
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodeLinkedTableName" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Private Function MyNodeForeignerKeys(M_DTLinks As DataTable) As List(Of String)
Try
Dim LinkedTableList As List(Of String) = Nothing
MyNodeForeignerKeys = Nothing
If M_DTLinks.Rows.Count > 1 Then
LinkedTableList = New List(Of String)
For i As Integer = 0 To M_DTLinks.Rows.Count - 1
Dim LinkedTableName As String = M_DTLinks.Rows(i).Item(2)
LinkedTableList.Add(LinkedTableName)
Next
MyNodeForeignerKeys = LinkedTableList
Return MyNodeForeignerKeys
Else
MyNodeForeignerKeys = M_DTLinks.Rows(0).Item(2)
Return MyNodeForeignerKeys
End If
Catch ex As Exception
MsgBox("Class Name: HDAS_TreeNode" + vbNewLine + "Method_Name: MyNodeForeignerKeys" + vbNewLine + "Error_Name: " + ex.Message)
End Try
End Function
Public Function DeepCopy() As HDAS_TreeNode
Dim theClone As HDAS_TreeNode = DirectCast(Me.MemberwiseClone(), HDAS_TreeNode)
theClone.HDAS_NodeName = String.Copy(HDAS_NodeName)
theClone.HDAS_NodeText = String.Copy(HDAS_NodeText)
theClone.HDAS_CurrentTable = String.Copy(HDAS_CurrentTable)
theClone.HDAS_PrimaryKeys = New List(Of String)(HDAS_PrimaryKeys)
theClone.HDAS_LinkedTables = New List(Of String)(HDAS_LinkedTables)
theClone.HDAS_ForeignerKeys = New List(Of String)(HDAS_ForeignerKeys)
theClone.HDAS_PropertiesFromDB = PropertiesFromDB.Copy
Return theClone
End Function
#End Region
End Class
What I expect is to have the Custom TreeNode in both TreeViews after the Drag and Drop process and methods to use Shallow and DeepCopy from my CUSTOM TreeNode. Please colleagues, I really need this...I am almost without sleep because of this. Any hint will be really appreciated. I am new doing all those things and sorry if I didn't made myself clear, English is not my native language. If you need additional explanation, feel free to ask, I am here to learn from you.
解决方案
Do not inherit HDAS_TreeNode
from TreeNode
. Use the standard TreeNode
, but store in its TreeNode.Tag
property, instances of HDAS_TreeNode
. So when you copy nodes between TreeView
's, you will end up with different TreeNode
instances pointing to the same HDAS_TreeNode
instance via their Tag
property.
In other words, instead of inheritance, use composition.
推荐阅读
- python - 使用 CBV 在同一模板上渲染 2 个模型
- noweb - 在 Windows 10 上安装 noweb 的安全、简单的方法是什么?
- tensorflow - Tensorflow freeze_graph 无法初始化 local_variables
- vuejs2 - 无法读取 null 的属性“getHours”
- javascript - D3.js 跨多个图同步缩放
- python - 将值添加到新数组
- javascript - 自动加载通过 webpack 生成的文件之间重复的代码
- javascript - 选项值变为未定义
- c++ - 图一个产品的两个整数的所有组合
- xamarin - Xamarin:构建已被取消