sql >> データベース >  >> RDS >> Access

ドラッグアンドドロップによるTreeViewノードの再配置

    はじめに。

    先週のImageComboControlに関するチュートリアルが、MicrosoftAccessプロジェクトに役立つことをご理解いただければ幸いです。 TreeView ImageComboコントロールを使用すると、いくつかのオプションを備えた美しいドロップダウンメニューを作成し、フォームの小さなスペースに配置することができます。

    同様に、以前のセッションでは、ノード階層の特定の場所に新しいノードを追加する方法、またはノードを削除して新しいノードを追加し、ツリービューコントロールのノードを再配置する方法を学習しました。

    このメソッドは、新しいノードのソーステーブルに新しいレコードの作成を要求します。または、既存のレコードを削除して新しいレコードを作成し、既存のノードを移動して永続的にします。ある意味で、追加/削除機能を使用すると、TreeViewコントロールで新しいノードを追加したり、既存のノードを再配置したりできます。ノードの再配置に関する限り、ノードを削除して再作成するよりも、より良い方法があります。ノードを現在の場所からドラッグし、TreeViewコントロール上の目的の場所にドロップします。これがこのエピソードで学ぶことです

    この単純なアプローチでは、変更を永続的にするために、関連するレコードのParentIDフィールド値の変更を更新するだけで済みます。

    これまでのセッションで取り上げたトピック。

    1. MicrosoftTreeViewControlチュートリアル
    2. TreeViewコントロールを使用したアクセスメニューの作成
    3. TreeViewコントロールへの画像の割り当て
    4. TreeViewControl-2への画像の割り当て
    5. TreeViewコントロールのチェックマーク-削除ノードの追加
    6. TreeViewImageComboドロップダウンアクセスメニュー

    ただし、この方法を使用しているときにいくつかの課題に直面する可能性があり、このセッションの後半でその問題に直面します。

    デモデータテーブルとフォーム。

    テーブルとフォームが必要です。 サンプルという名前の適切なテーブルがすでにあります 以前のチュートリアルセッションで作成されました。上記の2番目のリンクページからデモデータベースをすでにダウンロードしている場合は、このデータベースをこのセッションにも使用できます。ドラッグドロップ実験には、そのデータベースの次のオブジェクトを使用します。

    • 表:サンプル
    • フォーム: frmSample

    デモデータを含むfrmSampleのTreeViewコントロールイメージを参照用に以下に示します。

    デモデータベース( ProjectMenu.zip )をダウンロードできます )上記の2番目のリンクページから、 ProjectMenu.accdbを抽出します データベース。

    ドラッグドロップトライアルランの新しいフォーム。

    1. ProjectMenu.accdbデータベースを開きます。

    2. 表のコピーを作成するサンプル Sample_bk、という名前を付けます 安全に保管してください。後で変更せずに元のデータが必要になります。ドラッグアンドドロップメソッドを試すときは、サンプルデモテーブルのParentIdフィールド値を更新する必要があります。ただし、これらの変更を行わずに、後で元のデータが必要になります。

    3. frmDragDropという名前の新しいフォームを作成します 。

    4. frmDragDropフォームのデザインは、終了すると以下の画像のようになります。

    5. ActiveXコントロールのリストからTreeViewコントロールを挿入し、フォームに配置します。コントロールの上に十分なスペースを残して、2つのコマンドボタンとその上に見出しラベルを作成できるようにします。右下隅にあるサイズ変更ハンドルをドラッグして、スクロールせずにすべてのノードを表示するのに十分な大きさにします。

    6. 名前を変更します TreeViewControlのプロパティ値をTreeView0

    7. TreeViewコントロールの左上端にコマンドボタンを挿入します。 名前を変更する cmdExpandへのプロパティ値 およびキャプション すべて拡張の値 。

    8. TreeViewコントロールの右端の上と右端に2番目のコマンドボタンを挿入します。 名前を変更する cmdCollapseへのプロパティ値 およびキャプション プロパティ値をすべて折りたたむ
    9. 上記のように見出しを書き込むのに十分な幅のラベルコントロールをコマンドボタンの上に挿入し、フォントサイズ14を変更します。

    10. ImageListコントロールを無視します。当面の間、ノードのImageListインデックス番号を変更するコード行をコメントアウトしました。後で、以前のチュートリアルデモデータベース(上記の4番目のリンクページから)から手動でアップロードされた画像を使用してImageListコントロールをインポートし、それを使用してノード上のノード画像を表示できます。ドラッグドロップアクション中にノードの位置が変更された場合、TreeViewコントロール上のノードの位置(ルートレベルノードまたは子ノード)にも応じてノードイメージを変更する必要があります。

      フォームモジュールコードをドラッグドロップします。

    11. フォームfrmDragDropのVBAコードモジュールを表示し、次のVBAコード(これはフォームモジュールコードの前半のみ)をコピーしてfrmDragDropフォームのクラスモジュールに貼り付け、フォームを保存します。

      Option Compare Database
      Option Explicit
      
      Dim tv As MSComctlLib.TreeView
      Dim db As DAO.Database
      Dim rst As DAO.Recordset
      Dim imgListObj As MSComctlLib.ImageList
      Const KeyPrfx As String = "X"
      
      Private Sub Form_Open(Cancel As Integer)
      Set tv = Me.TreeView0.Object
      
      'Set imgListObj = Me.ImageList1.Object
      'tv.ImageList = imgListObj
      
      LoadTreeView
      
      End Sub
      
      Sub LoadTreeView()
      Dim strKey As String
      Dim strPKey As String
      Dim strText As String
      Dim strsQL As String
      
      strsQL = "SELECT * FROM Sample ORDER BY ID"
      
      Set db = CurrentDb
      Set rst = db.OpenRecordset(strsQL, dbOpenDynaset)
          
      tv.Nodes.Clear
      
      'Add all Items are added as Root Nodes
      Do While Not rst.BOF And Not rst.EOF
          strKey = KeyPrfx & CStr(rst!ID)
          strText = rst!desc
          tv.Nodes.Add , , strKey, strText
          
          'With tv.Nodes.Item(strKey)
          '    .Image = 1
          '    .SelectedImage = 4
          'End With
      
          rst.MoveNext
      Loop
      
      'Prepare to update the Parent-Key of Nodes
      'wherever applicable to move and position the Child Nodes
      strPKey = ""
      rst.MoveFirst
      Do While Not rst.EOF
          strPKey = Nz(rst!parentid, "")
          
          If Len(strPKey) > 0 Then
              strPKey = KeyPrfx & strPKey
              strKey = KeyPrfx & CStr(rst!ID)
              strText = rst!desc
              
              'Move the Child Node under it's Parent-Node
              Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)
              
      'Update Image and SelectedImage Properties
      'with ImageList Index numbers
              'With tv.Nodes.Item(strKey)
              '    .Image = 2
              '    .SelectedImage = 3
              'End With
      
          End If
          rst.MoveNext
      Loop
      
      rst.Close
      Set rst = Nothing
      Set db = Nothing
      
      End Sub
      
      
      Private Sub TreeView0_NodeClick(ByVal Node As Object)
      Dim SelectionNode As MSComctlLib.Node
          
      'Ensure that the clicked node equals the selected node in the tree
      If Not Node Is Nothing Then
          Set SelectionNode = Node
             If SelectionNode.Expanded = True Then
                  SelectionNode.Expanded = False
              Else
                  SelectionNode.Expanded = True
              End If
      End If
      End Sub
      
      Private Sub cmdCollapse_Click()
      Dim tmpnod As MSComctlLib.Node
      For Each tmpnod In tv.Nodes
          If tmpnod.Expanded = True Then
              tmpnod.Expanded = False
          End If
      Next
      
      End Sub
      
      Private Sub cmdExpand_Click()
      Dim tmpnod As MSComctlLib.Node
      For Each tmpnod In tv.Nodes
          If tmpnod.Expanded = False Then
              tmpnod.Expanded = True
          End If
      Next
      
      End Sub

      LoadTreeView()を除いて、以前のエピソードをすでに読んでいる場合は、上記のコードに精通していることを知っています。 いくつかの変更を加えたサブルーチン。ここでは、TreeViewノードへの入力は2段階のプロセスに分割されています。

      簡単に言うと、これがこのサブルーチンで行われることです。

      • のすべてのレコードサンプル 最初のステップで、テーブルはTreeView Controlのルートレベルノードとしてロードされ、IDフィールド値がキーになります。

      • 繰り返しますが、これらのレコードは2回目に読み取られ、 ParentId フィールドの場合、空の場合、ノードはルートレベルのノードとして保持されます。

      • ParentIDフィールドに値がある場合は、ParentID値を持つノードをNode-Keyとして識別します。現在のノードを子ノードとして移動するか、[ 相対] のパラメータ 追加() メソッド) 値が更新されます。

      • 2段階のノード入力手順は不要な演習であるように見えますが、この方法に従わなければならないのには十分な理由があります。少し後でこれに戻りますが、あまり説明しなくてもわかります。

      • フォームのデザインについて、ImageListコントロールを指定しました。 ImageList ActiveX Controlを挿入できます ディスクから手動でいくつかの画像をアップロードするか、このコントロールをコピーして、以前のデモデータベースダウンロードの画像と貼り付けます。いずれの場合も、ImageListコントロールの名前が ImageList1であることを確認してください。 。それ以外の場合は、コード内の名前を変更する必要があります。

      • その後、Form_Open()イベントプロシージャでコメント化された行を有効にします。行の先頭からコメント記号を削除して、次の行を有効にします。

        'Set imgListObj = Me.ImageList1.Object
        'tv.ImageList = imgListObj
        

      • TreeView0 _ OLEDragDrop() サブルーチン(VBAコードの2番目の部分)は、ノードの画像インデックスパラメーターを有効にします。これらの行からもコメント記号を削除します。これらの変更により、ノードイメージがTreeViewコントロールに表示されます。アップロードされた画像を含む独自のImageListコントロールがある場合は、ノードに挿入する画像に基づいてインデックス番号を変更します。

        TreeView0_NodeClick() イベントプロシージャ子ノードが折りたたまれた状態の場合は現在のノードを展開し、そうでない場合は子ノードが折りたたまれます。通常、このアクションは +/- をクリックすることで(コードなしで)制御されます 子ノードを持つノードのツリーライン上のシンボル。

        サブルーチンcmdExpand_Click() およびcmdCollapse_Click() イベントはすべてのノードを展開し、すべてのノードをそれぞれ折りたたみます。

        上記のコードを実行すると、表示は以下のフォームビュー画像のようになります。

      • frmDragDropを保存できます フォームを作成して、通常のビューで開きます。すべてが順調に進んだ場合は、上の画面が表示されます。 すべて拡張をお試しください およびすべて折りたたむ コマンドボタンを押して、それらも機能しているかどうかを確認します。そうでない場合は、次の設定が正しいかどうかを再確認してください。

      • i)TreeViewコントロールの名前は次のとおりです: TreeView0

      • ii)すべての例のプロパティシートを表示する コマンドボタンを押し、クリック時で[イベント手順]を選択します イベントプロパティ。

      • iii)すべて折りたたみで同じ設定が損なわれていないことを確認します コマンドボタンも。

      • iv)子ノードを持つノードをクリックして、繰り返しクリックすると折りたたまれるか展開されるかを確認します。

      • v)ImageListコントロールがフォームに配置されている場合、その名前は ImageList1である必要があります。

        ドラッグアンドドロップイベントを実装するVBAコードの2番目の部分に進みましょう。

      VBAコードの後半。

    12. ドラッグアンドドロップアクションを実装するVBAコードの次の2番目の部分をfrmDragDropフォームモジュールにコピーし、既存のコードの下に貼り付けます。

      Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long)
          Set Me.TreeView0.SelectedItem = Nothing
      End Sub
      
      
      Private Sub TreeView0_OLEDragOver(Data As Object, _
                                      Effect As Long, _
                                      Button As Integer, _
                                      Shift As Integer, _
                                      x As Single, _
                                      y As Single, _
                                      State As Integer)
          
          Dim SelectedNode As MSComctlLib.Node
          Dim nodOver As MSComctlLib.Node
          
          If tv.SelectedItem Is Nothing Then
              'Select a node if one is not selected
              Set SelectedNode = tv.HitTest(x, y)
              If Not SelectedNode Is Nothing Then
                  SelectedNode.Selected = True
              End If
          Else
              If tv.HitTest(x, y) Is Nothing Then
              'do nothing
              Else
                  'Highlight the node the mouse is over
                  Set nodOver = tv.HitTest(x, y)
                  Set tv.DropHighlight = nodOver
              End If
          End If
      
      End Sub
      
      
      Private Sub TreeView0_OLEDragDrop(Data As Object, _
                                          Effect As Long, _
                                          Button As Integer, _
                                          Shift As Integer, _
                                          x As Single, _
                                          y As Single)
      
          Dim sourceNode As MSComctlLib.Node
          Dim SourceParentNode As MSComctlLib.Node
          Dim targetNode As MSComctlLib.Node
          
          Dim tmpRootNode As MSComctlLib.Node
          Dim strtmpNodKey As String
          Dim ChildNode As MSComctlLib.Node
          
          Dim strSPKey As String
          Dim strTargetKey As String
          
          Dim strsQL As String
          Dim intKey As Integer
          Dim intPKey As Integer
          
          On Error Resume Next
          
          Select Case Screen.ActiveControl.Name
                  
                 Case TreeView0.Name
                      Set sourceNode = tv.SelectedItem
                  
          End Select
          
          'Get Source Parent Node & Target Node Reference
          Set SourceParentNode = sourceNode.Parent
          Set targetNode = tv.HitTest(x, y)
                  
          'If any errors then exit
          If Err <> 0 Then
              MsgBox Err & " : " & Err.Description, vbInformation + vbCritical, "OLEDragDrop()"
              Err.Clear
              Exit Sub
          Else
              On Error GoTo 0
          End If
          
      
          'Get/define Source parent Node Key to compare it with Target Node Key
          If SourceParentNode Is Nothing Then
              strSPKey = "Empty"
          Else
              strSPKey = SourceParentNode.Key
          End If
          
          'Check the Target Node/Location and define the Key
           Select Case True
              Case targetNode Is Nothing
                  strTargetKey = "Empty"
              
              Case targetNode.Key = ""
                  strTargetKey = "Empty"
                  Set targetNode = Nothing
              Case Else
                  strTargetKey = targetNode.Key
           End Select
          
          'Make sure the Target Node is not the source Node's own parent
          If strTargetKey = strSPKey Then Exit Sub
          
          'Track User's Node move action, check for error.
          On Error Resume Next
          
          If targetNode Is Nothing Then
              
              'If target Node is Nothing (the Node dropped in the empty area),
              'then the Node must be moved to the Root-level
              'save the original sourceNode.Key
              strtmpNodKey = sourceNode.Key
              
              'Modify the source Node Key, with addition of some text, say 'Empty', like 'X5Empty'
              'So that a temporary Node can be created with the original source Node key.
              'Note: Two Nodes with the same Key cannot remain in memory at the same time.
              'The Source Node with key 'X5Empty' deleted later,
              'temporary Node takes it's droped location.
              sourceNode.Key = sourceNode.Key & strTargetKey
      
              'Create the temporary Root Node, with original sourceNode Key
              Set tmpRootNode = tv.Nodes.Add(, , strtmpNodKey, sourceNode.Text)
              
              'define the Root Node image indexes
              'With tmpRootNode
              '    .Image = 1
              '    .SelectedImage = 4
              'End With
              
              'Move all child Nodes from SourceNode,if any,
              'as tmpRootNode's Children
              Do Until sourceNode.Children = 0
                  Set sourceNode.Child.Parent = tmpRootNode
                  
                  'modify Node image indexes
                  'With sourceNode
                  '    .Image = 2
                  '    .SelectedImage = 3
                  'End With
              Loop
      
              'Delete the Source Node with modified Key from TreeView
              tv.Nodes.Remove sourceNode.Index
              
              'Move the tmpRootNode with original Key
              'to the dropped location on TreeView
              Set sourceNode = tmpRootNode
          Else
              'Move the sourceNode under targetNode as child
              Set sourceNode.Parent = targetNode
              
              'modify Node image indexes
              'With sourceNode
              '    .Image = 2
              '    .SelectedImage = 3
              'End With
          End If
          
          'Notify, if there was an Error then Exit, else Update PrentID of related Record.
          If Err <> 0 Then
              MsgBox Err & " : " & "Unable to move:" & vbCrLf & Err.Description, vbInformation + vbCritical, "DragDrop2()"
              Exit Sub
          Else
              'Build and execute the SQL statement to update the record
              If targetNode Is Nothing Then
                  intKey = Val(Mid(sourceNode.Key, 2))
                  strsQL = "UPDATE Sample SET ParentID = Null" & _
                           " WHERE ID = " & intKey
              Else
                  intKey = Val(Mid(sourceNode.Key, 2))
                  intPKey = Val(Mid(targetNode.Key, 2))
                  
                  strsQL = "UPDATE sample SET ParentID = " & intPKey & _
                           " WHERE ID = " & intKey
              End If
              
              'Modify the table records
              CurrentDb.Execute strsQL, dbFailOnError
              
              'If an error raised then refresh TreeView and exit
              If Err <> 0 Then
                  MsgBox Err & " : " & Err.Description
                  LoadTreeView 'Refresh/display TreeView without changes
              Else
                  'Sort Nodes
                  If sourceNode.Parent Is Nothing Then
                      sourceNode.Root.Sorted = True
                  Else
                      sourceNode.Parent.Sorted = True
                  End If
                  
                  tv.Nodes(sourceNode.Key).Selected = True
              End If
          End If
          On Error GoTo 0
      
      End Sub
      
      Private Sub TreeView0_OLECompleteDrag(Effect As Long)
      
          'Turn off the drophighlight
          Set tv.DropHighlight = Nothing
      
      End Sub
      
      Private Sub Form_Close()
      
      Set tv = Nothing
      End Sub

    ドラッグアンドドロップアクションには、4つのサブルーチンがあり、ノードをドラッグすると自動的に実行され、他のノードに移動するとノードが強調表示され、最後に別のノードまたはルートレベルの空の領域にドロップされます。 。

    コードの主なサブルーチン。

    • TreeView0_OLEStartDrag() -選択したアイテムを初期化し、ノードをなしに設定します
    • TreeView0_OLEDragOver()- マウス移動イベントのように機能し、ノードをその上にドラッグすると、ターゲットノードに向かう途中でノードが強調表示されます。
    • TreeView0_OLEDragDrop()– チェックと制御を実行し、ノードをドロップされた場所に配置し、ベーステーブルのレコードを更新します。
    • TreeView0_OLECompleteDrag() -DropHighlightプロパティはNothingに設定されています。

    TreeView0_OLEDragDrop()を使用して、ドラッグアンドドロップ作業を実行できます。 サブルーチンのみ。その場合、以下のサンプル画像のように、マウスポインターがその後ろにある2番目の矢印をドラッグするように変わることを除いて、ソースノードが他のノード上をある場所から別の場所に移動するときにノードハイライトはありません。 :

    そのため、このサブルーチンに注意を払い、コードを最初から詳細に確認します。サブルーチンの開始時に、必要なノードと文字列変数などを宣言しました。

    ここで行ごとの分析を繰り返す代わりに、コードの各行/セクションに適切にコメントして、コードを実行するときにそれが何をするかを理解できるようにしました。あなたはそれらを通り抜けることができます。

    ドレープドロップイベントのシーケンス

    ユーザーが選択するイベントのシーケンスを理解しましょう ノード、最終目的地に向かう途中で他のノードをドラッグし、ドロップ ターゲットノード上にあります。または、TreeViewコントロールの空の領域にドロップして、ルートレベルのノードにします。

    ノードを別のノードテキストの上にドラッグすると、ノードテキストが強調表示され、ここからどこへ行っても、現在の位置がこのノード上にあることが示されます。ノードテキストから移動すると、ハイライトが消えます。これは、ターゲットノードに至るまで発生します。 TreeView0_OLEDragOver() サブルーチンは、この強調表示アクションを処理します。

    TreeView0_OLEDragDrop()のどこかにノードをドロップすると サブルーチンは過充電になります。ここでは、ユーザーの意図を分析し、適切な措置を講じる必要があります。ノードを正しい場所に移動するには、次の情報を保存して分析する必要があります。

    追跡する重要な情報。

    1. ソースノードリファレンス、ノードキーとParentID値、ノードの子(存在する場合)。

    2. ターゲットノードまたはロケーション参照、ノードキー。

    3. ターゲットがノードではなく、TreeViewコントロールの空の領域である場合、ソースノードはルートレベルの位置に移動されます。

    4. ソースノードが別のノードにドロップされると、ターゲットノードがソースノードの新しい親になります。

    5. ソースノードに独自の子がある場合は、それらも親と一緒に移動する必要があります。

    6. ** ノードがそれ自体の親ノードにドラッグアンドドロップされた場合、このアクションを無視します。

      ** たとえば、上の画像を確認してください。 TextBoxをドラッグすると ノードを作成し、その親ノードにドロップしますコントロール、 またはコントロールをドラッグします ノードを作成し、その親ノードのフォームにドロップします その後、それらの動きは無視されます。

    7. ** ルートレベルの場合 ノードは空の領域にドラッグアンドドロップされます。すでにルートレベルのノードであるため、アクションは実行されません。

    ノードのすべての有効な移動について、 ParentIDを更新する必要があります サンプルの関連レコードのフィールド値 テーブル。

    ルートレベルの空の領域でのノードドロップ。

    アイテム番号3の場合 上記では、ソースノードと同じID番号でルートレベルノードを作成する必要がありますが、これは許可されていません。 TreeView階層では、重複するキー値は許可されていません。これはコードの唯一の領域であり、そこで行われる手順について少し混乱するでしょう。

    手順は以下のとおりです。

    1. いくつかのテキストを追加して、既存のTreeViewノードキーを変更します(たとえば、キー X5 変更 X5Empty )、元のキーを使用して一時ノードを作成するときに、キーの競合を回避するため。

    2. 一時的なを作成します 元のキーを持つノード:X5。

    3. すべての子ノードをソースノード(存在する場合)から子ノードとして一時ノードに移動します。

    4. キーが変更されたTreeViewソースノードを削除します: X5Empty TreeViewコントロールから ただし、サンプルテーブルの関連レコードは変更されていません。

    5. 一時的を移動します 元のキーを持つノードX5 子と一緒にTreeViewコントロールのルートレベルの位置に移動します。

    6. 関連するレコードのParentIDフィールドを長さゼロの文字列( "")で更新して、ルートレベルのノードとしてマークします。

    ドラッグドロップの自己実験。

    ドラッグアンドドロップの実験を自分で試して、それがどのように機能するかを確認することができます。ノードを選択し、マウスの左ボタンをクリックして押したまま、ノードをドラッグして別のノードにドロップするか、TreeViewコントロールの空の領域にドロップします。ノードを他のノードテキストの上にドラッグすると強調表示され、ノードの外にいると強調表示が消えます。ドラッグしたノードは、ドロップした新しい場所に表示されます。単一のノードまたは子を持つノードを選択することで、このドラッグドロップ実験を繰り返すことができます。

    このノードの移動に基づいて、関連するレコードの ParentID フィールド値はキーで更新されます ターゲットノード関連レコードの値(ID)。

    なぜ2ステップのノード入力手順なのか?

    ここで、 LoadTreeView()に戻ります。 サブルーチン、すべてのノードをTreeViewコントロールに移入するために採用した2段階のプロセスをもう一度見てみましょう。

    • サンプルのすべてのレコード テーブルは、最初はルートレベルのノードとして追加され、IDフィールドの値をノードキーとして使用します。

    • レコードの2番目のパスで、ParentIDフィールドの値が空の場合、そのノードは変更されずにルートレベルのノードのままになります。

    • ParentID値を持つ他のすべてのノード関連のレコードは、その親ノードの下に正しく移動されます。

    当然のことながら、なぜこのようにしなければならないのかという疑問が生じます。

    簡単な実験をして、あまり多くの言葉で説明せずに答えを明確にします。ドラッグアンドドロップの試行を自分で実行し、ノードを再配置したことがあるかもしれません。その過程で、これらのレコードのParentID値が変更されて更新されました。そのため、サンプルでレコード値を元の状態にリセットする必要があります 表、新しいデモを開始する前。

    テーブルのサンプルのコピーはすでに作成されています 以前は、 Sample_bkという名前で バックアップとして サンプルを削除します テーブルを作成し、 Sample_bkからコピーを作成します 元の名前:サンプル

    テーブルを開き、レコードとそのParentIDフィールドの値を表示します。表のサンプル画像を以下に示します。

    IDフィールド値はオートナンバーであり、すべて順番に並んでおり、すべてのID値は一意です。次の単純なルールは、TreeViewコントロールへの子ノードの追加を管理します。

    単純な子ノードルール: ParentID フィールド値(親キー )レコード内では、親ノードがTreeViewコントロールにすでに存在し、ノードキーと同じ値であることが想定されています。 (ID)

    上の表の画像で、上から3番目のレコードを確認してください。 ParentIDフィールドの値は2で、現在のレコードのIDは3です。この場合、3番目のレコードをノードに追加する前に、ID2のレコードがTreeViewコントロールに追加されます。両方のレコードが必ずしも隣り合っているとは限りません。 ID番号21のレコードを確認してください。そのParentIDフィールド値は12であり、現在のレコードID値21よりも小さくなっています。

    いずれの場合も、プログラムがレコード内でParentID値を検出すると、ノードにデータを入力する前のサイクルで、ParentIDと等しいID値を持つレコードがTreeViewコントロールのノードとしてすでに追加されていると見なされます。

    2ステップの手順を正当化する。

    ドラッグドロップの試運転を試してみましょう。ただし、その前に、 frmSample、という名前のフォームがあります。 これ 最初のチュートリアルセッションで使用し、すべてのTreeViewノードを一度にロードしました。はい、これまでも同じ方法で行ってきましたが、今後は変更が必要です。ただし、その前に、古いフォームを開いて、ノードがフォームにどのように表示されるかを確認しましょう。

    1. フォームfrmSampleを開きます 古いルールを使用してロードされたサンプルテーブルレコードを使用して、TreeViewの表示がどのように表示されるかを確認します。

    2. TreeViewノードを表示している場合は、フォームを閉じます。

    3. 次に、 frmDragDropを開きます 形。ノードをドラッグアンドドロップする準備をしています。

    4. ノードテキストテーブル、でノードを選択します マウスの左ボタンをクリックして押したまま、ノードテキストフォームを使用してノードにドラッグアンドドロップします。

    5. テーブル 直接の子ノードフィールドを持つノード およびその子ノードは、フォームの下で子ノードとして移動されます ノード。

    6. フォームを閉じるfrmDragDrop もう一度開きます。以下の画像のように、ノードをドロップした場所にノードが正しく表示されます。

    7. 次に、フォームfrmDragDropを閉じます。

    8. フォームfrmSampleを開きます この変更がこのフォームにどのように表示されるかを確認します。エラーメッセージElement Not Foundが表示されます エラー番号:35601。

    9. デバッグコマンドボタンを選択して、エラーが発生した強調表示されたコード行に移動します。

    10. nodKeyにマウスを合わせます Add()メソッドのパラメータ。 X3、を表示します。 ポイント ParentKey上のマウス パラメータとそれはX7を示しています。

      これらの2つのパラメータ値を見ると、ID値3のレコードにあり、このノードを、ID値7のTreeViewコントロールにまだ入力されていない別のノードの子ノードとして指定しようとしていると想定できます。

    11. F5を押します キーを押して同じダイアログボックスを再度表示し、終了をクリックします プログラムを停止し、データベースウィンドウにフォームを表示するためのコマンドボタン。 frmSampleフォームを閉じます。

    12. サンプルを開きます ドラッグアンドドロップアクション後のParentID番号の配置を表示するテーブル。レコードは以下の画像のようになり、ParentID値 7でエラーをトリガーしたレコードを強調表示しました 親レコードの位置を表示します

    以前のノード入力の通常の手順に従って、3番目のレコード位置にいます。以来、ParentID値7を記録し、ID値 7のNodを記録します。 TreeViewコントロールに存在する必要があります。 ID値が7のノード はまだTreeViewコントロールに入力されていませんが、存在しないノードを参照しようとしているため、エラーが発生します。

    ParentIDフィールドの順序でレコードを並べ替えても、レコードの新しい配置は次の画像のようになります。

    現在、別のレコードの親ノードが予期された位置にありません。

    したがって、このような状況では、2段階のTreeViewノードの読み込みアプローチは、通常のアクションとドラッグドロップ後のアクションの両方で機能します。

    最初のステップでは、IDフィールド値をNode-Keyとして使用して、TreeViewコントロールのルートレベルノードとしてすべてのレコードにデータを入力します。

    これで、すべてのレコードのすべてのノードがTreeViewコントロールで使用できるようになります。どこにでも簡単に移動できます。必要なノードがTreeViewに存在しないとは言えません。

    同じレコードセットの2回目のパスでは、ParentIDフィールドの値が空のレコードは変更されず、ルートレベルのノードとして残ることができます。 In other cases moves the Node as Child-Node under its Parent Node, by updating the [Relative] Parameter of the Node with the following Statement:

    Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)

    This is what we do through the second pass on the same set of records. You may do it by resetting the Record Pointer to the first record, by executing rst.MoveFirst before the Do . 。 。 Loop, EOF conditions and rst.MoveNext to access each record as we normally do.

    Second Step in Reverse Order.

    Or you may do it in reverse order. After populating all records as Root-level Nodes the Record Pointer will be beyond the last record and on the EOF ポジション。 You may reset the record pointer to the last record, by executing rst.MoveLast before the Do . 。 。 Loop BOF check, and execute rst.MovePrevious to access each record and move the Nodes correctly under its p arent Node. But, the Nodes may load slightly differently in the placement order of Nodes.

    You may try this out yourself with the above-suggested change of Code and see the result.

    Download Demo Database


    1. MS-AccessクラスモジュールとVBA
    2. MS-AccessVBAクラスオブジェクト配列
    3. MS-Accessの基本クラスと派生オブジェクト
    4. VBA Base Class and Derived Object-2
    5. 基本クラスと派生オブジェクトのバリアント
    6. MS-Access Recordset and Class Module
    7. アクセスクラスモジュールとラッパークラス
    8. ラッパークラスの機能変換


    1. 警告:mysql_fetch_array()は、パラメーター1がリソースであると想定しています。ブール値は次のように指定されます。

    2. SQL Serverで「datetime」を「date」に変換する(T-SQLの例)

    3. MySQLGroupByおよびOrde​​rBy

    4. Oracle SQLで特定の文字までの部分文字列を選択するにはどうすればよいですか?