2010-08-04 94 views
3

我正在將VB6應用程序遷移到.Net,我們必須始終提供類似功能的功能。在一種形式中是具有複選框的樹形視圖,其具有三個級別的節點。第一級僅用於將下一級分組,並且它們不可檢查。第二級節點可由用戶檢查,當選中或取消選中時,其所有孩子都會效仿。無論檢查狀態是否受到影響,在所有級別,單擊節點或其複選框都將意味着它被選中。.Net Treeview事件處理

第三個層次是問題的癥結所在(儘管問題本身在所有treeview複選框中都有所體現):該層包含兩個節點類型,一個可以由用戶檢查和取消選中(如果父類是檢查)以及一種類型,無論父母的狀態如何,用戶都無法檢查或取消選中,但其狀態與其父母的狀態相同。

在正常使用中,這一切都按預期工作。但是,如果您快速點擊第三層節點之一(不應該直接檢查)兩次,它似乎會更改其檢查狀態。但是,如果您檢查Checked屬性的基礎值,它將保持不受影響,因此它看起來只是一個顯示問題。如果發現,這種異常將成爲我們客戶的一個問題,因爲用戶可能認爲他們可以做一些他們不能導致昂貴混淆的事情。

我剛剛從這一想法的新鮮 - 有任何人觀察到這種行爲或知道它,並有解決方法/解決方案嗎?我不禁感到我錯過了一些非常明顯的事情,但在一天半之後,我現在擁有隧道視野。這裏有一些代碼來演示這個問題。創建一個樹狀形式(大到足以看到發生了什麼事情)和兩個按鈕,然後放棄這一在:

Private _node As TreeNode = Nothing 


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 

    MessageBox.Show(_node.Text & " : " & _node.Checked.ToString) 
    _node = Nothing 

End Sub 

Private Sub InitialiseTreeview() 

    TreeView1.Nodes.Clear() 

    Dim ran As New Random 
    Randomize() 

    For i As Int32 = 1 To 5 
     Dim TLNode As New TreeNode 
     Dim children As Int32 = 0 

     children = ran.Next(1, 5) 

     TLNode.Text = "Top Level Node " & i.ToString 

     For j As Int32 = 1 To children 
      TLNode.Nodes.Add("Child Node " & j.ToString) 
     Next 

     TreeView1.Nodes.Add(TLNode) 
    Next 

    TreeView1.ExpandAll() 
End Sub 

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    InitialiseTreeview() 
End Sub 


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
    InitialiseTreeview() 
End Sub 

運行它,然後單擊一個節點上一次。點擊按鈕1,它會告訴你節點文本和它的檢查狀態。現在,快速點擊相同節點複選框兩次,觀察複選標記的狀態並再次單擊按鈕1。你會明白我的意思。按鈕2生成一組新的樹節點。

回答

5

是的,這是Vista本地TreeView控件引入的一個bug。當它看到雙擊事件時,它會自動切換項目的檢查狀態。如果不告訴.NET TreeView包裝器,Before/AfterCheck事件將不會運行。這在.NET包裝器中沒有被修復,可能永遠不會。

解決此錯誤需要防止本機控制看到雙擊消息。爲您的項目添加一個新類並粘貼下面顯示的代碼。編譯。將新的控件從工具箱的頂部拖放到窗體上,替換現有的TreeView。

Public Class MyTreeView 
    Inherits TreeView 

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
     '' Filter the WM_LBUTTONDBLCLK message 
     If m.Msg <> &H203 Then MyBase.WndProc(m) 
    End Sub 

End Class 
+0

謝天謝地 - 我以爲我失去了理智。我已經實現了你的建議解決方案,它的工作原理絕對完美非常感謝您的快速響應和示例解決方法代碼。如果我有足夠的聲望,我會投你的答案,但我還沒有到那裏! – 2010-08-05 11:11:49

+0

啊,突然我有足夠的代表投票了! – 2010-08-05 11:16:39

+1

微軟爲什麼不解決這個問題? – Andrew 2012-12-14 13:01:56