TreeViewの親ノードのチェックボックスをダブルクリックすると、子ノードに親ノードのチェック状態が反映されない場合がある

現象
チェックボックスを追加した TreeView コントロールの親ノードのチェック状態が変更された時、全ての子ノードに親ノードのチェック状態を反映させることができます。しかし、コモンコントロール (Comctl32) バージョン 6 の TreeView コントロールにおいて親ノードのチェックボックスをダブルクリックした場合、子ノードにチェック状態が反映されない問題が発生することがあります。
原因
本現象は、Windows Vista 以降の OS で利用可能なコモンコントロール (Comctl32) バージョン 6 の問題により発生しています。 Comctl32 バージョン 6 の TreeView では、ダブルクリックを行うと、クリックしたチェックボックスに対して内部的にシングルクリックを 2 回実行する処理が行われています。この処理が原因となり、親ノードは 2回チェック処理が行われますが子ノードは 1 回チェックされた状態になり、親ノードと子ノードの整合性がとれない状態になります。
状況
マイクロソフトでは、この問題をこの資料の対象製品として記載されているマイクロソフト製品の問題として認識しています。
詳細
[現象を再現する手順]
1. Visual Studio から新しいWindows フォーム アプリケーションを作成します。

2. フォームに TreeView コントロールを追加します。

3. 次の手順から親ノードと子ノードを追加します。

・TreeView コントロールを右クリックして[ノードの編集…]を選択。
・TreeNode エディターにて[ルートの追加]をクリック。
・[子の追加]を2回クリックして子ノードを2つ追加。
・OK でエディタを閉じます。

4. TreeView の CheckBoxes プロパティを True に設定します。

5.子ノードに親ノードのチェック設定を反映するため、TreeView に AfterCheck イベントハンドラを追加します。
Private Sub CheckAllChildNodes(treeNode As TreeNode, nodeChecked As Boolean)   Dim node As TreeNode   For Each node In  treeNode.Nodes       node.Checked = nodeChecked      If node.Nodes.Count > 0 Then          Me.CheckAllChildNodes(node, nodeChecked)      End If    Next nodeEnd Sub  Private Sub node_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles treeView1.AfterCheck   If e.Action <> TreeViewAction.Unknown Then        If e.Node.Nodes.Count > 0 Then          Me.CheckAllChildNodes(e.Node, e.Node.Checked)      End If    End If End Sub

6.アプリケーションを実行します。

[結果]
アプリケーションを起動すると、チェックボックスをもった TreeView コントロールが表示されます。[+] から子ノードを表示し、親ノードのチェックボックスをダブルクリックすると、親ノードと子ノードのチェックの状態が一致しない現象が発生します。

[回避手順]
チェックボックス上でのダブルクリックイベントを無視し、シングルクリックが行われたと判定することにより、本現象を回避することができます。これは、TreeView コントロールの WndProc メソッドにて、受けた WM_LBUTTONDBLCLK イベントを無視することで実現します。

1. フォーム のプロジェクトに新しいクラスを追加します。

2. クラス名をTreeViewExとします

3. TreeView を継承し、WndProc 関数をオーバーライドします。

Partial Public Class TreeViewExInherits TreeViewProtected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)      If m.Msg = &H203 Then      m.Result = IntPtr.Zero      Else      MyBase.WndProc(m)   End IfEnd Sub End Class

4. デザイナーにて TreeView の代わりに TreeViewEx を利用するための変更を行います。

変更前:Me.TreeView1 = New System.Windows.Forms.TreeView()
変更後:Me.TreeView1 = New TreeViewEx()

変更前:Friend WithEvents TreeView1 As System.Windows.Forms.TreeView
変更後:Friend WithEvents TreeView1 As TreeViewEx
注意 : これは、マイクロソフトのサポート組織内で直接作成された "緊急公開" の資料です。 この資料には、確認中の問題に関する現状ベースの情報が記載されています。 情報提供のスピードを優先するため、資料には誤植が含まれる可能性があり、予告なしに随時改定される場合があります。 その他の考慮事項については、使用条件を参照してください。
プロパティ

文書番号:2781622 - 最終更新日: 09/29/2016 14:43:00 - リビジョン: 4.0

  • KB2781622
フィードバック