はじめに。
先週のImageComboControlに関するチュートリアルが、MicrosoftAccessプロジェクトに役立つことをご理解いただければ幸いです。 TreeView ImageComboコントロールを使用すると、いくつかのオプションを備えた美しいドロップダウンメニューを作成し、フォームの小さなスペースに配置することができます。
同様に、以前のセッションでは、ノード階層の特定の場所に新しいノードを追加する方法、またはノードを削除して新しいノードを追加し、ツリービューコントロールのノードを再配置する方法を学習しました。
このメソッドは、新しいノードのソーステーブルに新しいレコードの作成を要求します。または、既存のレコードを削除して新しいレコードを作成し、既存のノードを移動して永続的にします。ある意味で、追加/削除機能を使用すると、TreeViewコントロールで新しいノードを追加したり、既存のノードを再配置したりできます。ノードの再配置に関する限り、ノードを削除して再作成するよりも、より良い方法があります。ノードを現在の場所からドラッグし、TreeViewコントロール上の目的の場所にドロップします。これがこのエピソードで学ぶことです
この単純なアプローチでは、変更を永続的にするために、関連するレコードのParentIDフィールド値の変更を更新するだけで済みます。
これまでのセッションで取り上げたトピック。
- MicrosoftTreeViewControlチュートリアル
- TreeViewコントロールを使用したアクセスメニューの作成
- TreeViewコントロールへの画像の割り当て
- TreeViewControl-2への画像の割り当て
- TreeViewコントロールのチェックマーク-削除ノードの追加
- TreeViewImageComboドロップダウンアクセスメニュー
ただし、この方法を使用しているときにいくつかの課題に直面する可能性があり、このセッションの後半でその問題に直面します。
デモデータテーブルとフォーム。
テーブルとフォームが必要です。 サンプルという名前の適切なテーブルがすでにあります 以前のチュートリアルセッションで作成されました。上記の2番目のリンクページからデモデータベースをすでにダウンロードしている場合は、このデータベースをこのセッションにも使用できます。ドラッグドロップ実験には、そのデータベースの次のオブジェクトを使用します。
- 表:サンプル
- フォーム: frmSample
デモデータを含むfrmSampleのTreeViewコントロールイメージを参照用に以下に示します。
デモデータベース( ProjectMenu.zip )をダウンロードできます )上記の2番目のリンクページから、 ProjectMenu.accdbを抽出します データベース。
ドラッグドロップトライアルランの新しいフォーム。
-
ProjectMenu.accdbデータベースを開きます。
-
表のコピーを作成するサンプル Sample_bk、という名前を付けます 安全に保管してください。後で変更せずに元のデータが必要になります。ドラッグアンドドロップメソッドを試すときは、サンプルデモテーブルのParentIdフィールド値を更新する必要があります。ただし、これらの変更を行わずに、後で元のデータが必要になります。
-
frmDragDropという名前の新しいフォームを作成します 。
-
frmDragDropフォームのデザインは、終了すると以下の画像のようになります。
-
ActiveXコントロールのリストからTreeViewコントロールを挿入し、フォームに配置します。コントロールの上に十分なスペースを残して、2つのコマンドボタンとその上に見出しラベルを作成できるようにします。右下隅にあるサイズ変更ハンドルをドラッグして、スクロールせずにすべてのノードを表示するのに十分な大きさにします。
-
名前を変更します TreeViewControlのプロパティ値をTreeView0 。
-
TreeViewコントロールの左上端にコマンドボタンを挿入します。 名前を変更する cmdExpandへのプロパティ値 およびキャプション すべて拡張の値 。
- TreeViewコントロールの右端の上と右端に2番目のコマンドボタンを挿入します。 名前を変更する cmdCollapseへのプロパティ値 およびキャプション プロパティ値をすべて折りたたむ
-
上記のように見出しを書き込むのに十分な幅のラベルコントロールをコマンドボタンの上に挿入し、フォントサイズ14を変更します。
-
ImageListコントロールを無視します。当面の間、ノードのImageListインデックス番号を変更するコード行をコメントアウトしました。後で、以前のチュートリアルデモデータベース(上記の4番目のリンクページから)から手動でアップロードされた画像を使用してImageListコントロールをインポートし、それを使用してノード上のノード画像を表示できます。ドラッグドロップアクション中にノードの位置が変更された場合、TreeViewコントロール上のノードの位置(ルートレベルノードまたは子ノード)にも応じてノードイメージを変更する必要があります。
フォームモジュールコードをドラッグドロップします。
-
フォーム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コードの後半。
-
-
ドラッグアンドドロップアクションを実装する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()のどこかにノードをドロップすると サブルーチンは過充電になります。ここでは、ユーザーの意図を分析し、適切な措置を講じる必要があります。ノードを正しい場所に移動するには、次の情報を保存して分析する必要があります。
追跡する重要な情報。
-
ソースノードリファレンス、ノードキーとParentID値、ノードの子(存在する場合)。
-
ターゲットノードまたはロケーション参照、ノードキー。
-
ターゲットがノードではなく、TreeViewコントロールの空の領域である場合、ソースノードはルートレベルの位置に移動されます。
-
ソースノードが別のノードにドロップされると、ターゲットノードがソースノードの新しい親になります。
-
ソースノードに独自の子がある場合は、それらも親と一緒に移動する必要があります。
-
** ノードがそれ自体の親ノードにドラッグアンドドロップされた場合、このアクションを無視します。
** たとえば、上の画像を確認してください。 TextBoxをドラッグすると ノードを作成し、その親ノードにドロップしますコントロール、 またはコントロールをドラッグします ノードを作成し、その親ノードのフォームにドロップします その後、それらの動きは無視されます。
-
** ルートレベルの場合 ノードは空の領域にドラッグアンドドロップされます。すでにルートレベルのノードであるため、アクションは実行されません。
ノードのすべての有効な移動について、 ParentIDを更新する必要があります サンプルの関連レコードのフィールド値 テーブル。
ルートレベルの空の領域でのノードドロップ。
アイテム番号3の場合 上記では、ソースノードと同じID番号でルートレベルノードを作成する必要がありますが、これは許可されていません。 TreeView階層では、重複するキー値は許可されていません。これはコードの唯一の領域であり、そこで行われる手順について少し混乱するでしょう。
手順は以下のとおりです。
-
いくつかのテキストを追加して、既存のTreeViewノードキーを変更します(たとえば、キー X5 変更 X5Empty )、元のキーを使用して一時ノードを作成するときに、キーの競合を回避するため。
-
一時的なを作成します 元のキーを持つノード:X5。
-
すべての子ノードをソースノード(存在する場合)から子ノードとして一時ノードに移動します。
-
キーが変更されたTreeViewソースノードを削除します: X5Empty TreeViewコントロールから、 ただし、サンプルテーブルの関連レコードは変更されていません。
-
一時的を移動します 元のキーを持つノードX5 子と一緒にTreeViewコントロールのルートレベルの位置に移動します。
-
関連するレコードの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ノードを一度にロードしました。はい、これまでも同じ方法で行ってきましたが、今後は変更が必要です。ただし、その前に、古いフォームを開いて、ノードがフォームにどのように表示されるかを確認しましょう。
-
フォームfrmSampleを開きます 古いルールを使用してロードされたサンプルテーブルレコードを使用して、TreeViewの表示がどのように表示されるかを確認します。
-
TreeViewノードを表示している場合は、フォームを閉じます。
-
次に、 frmDragDropを開きます 形。ノードをドラッグアンドドロップする準備をしています。
-
ノードテキストテーブル、でノードを選択します マウスの左ボタンをクリックして押したまま、ノードテキストフォームを使用してノードにドラッグアンドドロップします。
-
テーブル 直接の子ノードフィールドを持つノード およびその子ノードは、フォームの下で子ノードとして移動されます ノード。
-
フォームを閉じるfrmDragDrop もう一度開きます。以下の画像のように、ノードをドロップした場所にノードが正しく表示されます。
-
次に、フォームfrmDragDropを閉じます。
-
フォームfrmSampleを開きます この変更がこのフォームにどのように表示されるかを確認します。エラーメッセージElement Not Foundが表示されます エラー番号:35601。
-
デバッグコマンドボタンを選択して、エラーが発生した強調表示されたコード行に移動します。
-
nodKeyにマウスを合わせます Add()メソッドのパラメータ。 X3、を表示します。 ポイント ParentKey上のマウス パラメータとそれはX7を示しています。
これらの2つのパラメータ値を見ると、ID値3のレコードにあり、このノードを、ID値7のTreeViewコントロールにまだ入力されていない別のノードの子ノードとして指定しようとしていると想定できます。
-
F5を押します キーを押して同じダイアログボックスを再度表示し、終了をクリックします プログラムを停止し、データベースウィンドウにフォームを表示するためのコマンドボタン。 frmSampleフォームを閉じます。
-
サンプルを開きます ドラッグアンドドロップアクション後の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
- MS-AccessクラスモジュールとVBA
- MS-AccessVBAクラスオブジェクト配列
- MS-Accessの基本クラスと派生オブジェクト
- VBA Base Class and Derived Object-2
- 基本クラスと派生オブジェクトのバリアント
- MS-Access Recordset and Class Module
- アクセスクラスモジュールとラッパークラス
- ラッパークラスの機能変換