2010-01-06 70 views
3

這是我所期待的事:TreeView節點是否具有中間檢查狀態?

  • 代表一組選項,按類別劃分。
  • 允許用戶通過選中/取消選中類別節點來選中/取消選中某個類別中的所有項目。
  • 顯示類別中的某些選項是通過將類別節點設置爲中間選中狀態來檢查的。

從我讀過,我用的TreeView經驗有限,這最後的希望不出現可能的,因爲樹節點似乎不支持比開/關選中狀態的任何其他。這可能使用TreeView嗎?有沒有其他的控件可以解決這個問題,或者我將不得不做一個TreeView的子類來完成它?

+0

嗨,處理「不確定的複選框的狀態在一個TreeView(不含涉水到子類中的WinForms原生樹視圖的‘沼澤’,這是一個包裝圍繞一個「化石」,真的很難分類和創建自定義「繪畫」的所有者繪製的版本)是我使用第三種的一個原因。第三方TreeView具有您正在描述的內置功能。你可以查看我在SO上使用這篇文章的評論:http://stackoverflow.com/questions/1983600/c-treeview-check-number-of-checked-children/1983715#1983715 – BillW 2010-01-06 03:13:17

回答

0

我想你必須自己寫這個功能。您可以保持簡單,只需將複選框的顏色設爲淺灰色或顯示中間狀態即可。

如果您使用的是WPF,我認爲您可能可以更改樹視圖的控件模板和/或複選框的控件模板。

在WPF中,我會說這將是更容易實現,然後winforms。不確定你在這種情況下使用的是什麼技術。

2

它可以通過使用DrawMode屬性來完成,因此您可以使用ControlPaint.DrawCheckBox()繪製自己的複選框。您還必須實施MouseDown事件並使用HitTest方法檢測假複選框上的點擊。沒有太大的喜悅,但它是可能的。

1

您可以使用支持三種狀態checkBoxes的自定義TreeView,例如this one

0

這是我的解決方案形式,Windows Vista和更高:

Public Structure TV_ITEM 
    Public mask As UInteger 
    Public hItem As IntPtr 
    Public state As UInteger 
    Public stateMask As UInteger 
    <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.LPTStr)> 
    Public pszText As String 
    Public cchTextMax As Integer 
    Public iImage As Integer 
    Public iSelectedImage As Integer 
    Public cChildren As Integer 
    Public lParam As IntPtr 
End Structure 

Public Class TreeViewEx 
    Inherits TreeView 
    Private Const TVIF_HANDLE As UInteger = &H10 
    Private Const TVIF_STATE As UInteger = &H8 
    Private Const TVIS_STATEIMAGEMASK As UInteger = &HF000 
    Private Const TV_FIRST As UInteger = &H1100 
    Private Const TVM_SETITEM As UInteger = TV_FIRST + 13 
    Private Const TVM_SETEXTENDEDSTYLE As UInteger = TV_FIRST + 44 
    Private Const TVS_EX_DOUBLEBUFFER As UInteger = &H4 
    Private Const TVS_EX_PARTIALCHECKBOXES As UInteger = &H80 

    Private Declare Auto Function SendMessage Lib "user32" (ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByRef lParam As TV_ITEM) As IntPtr 
    Private Declare Auto Function SendMessage Lib "user32" (ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr 

    Private Function INDEXTOSTATEIMAGEMASK(i As Integer) As Integer 
     Return i << 12 
    End Function 

    Protected Overrides Sub OnHandleCreated(e As System.EventArgs) 
     Dim style As UInteger = TVS_EX_DOUBLEBUFFER Or TVS_EX_PARTIALCHECKBOXES 
     SendMessage(Me.Handle, TVM_SETEXTENDEDSTYLE, New IntPtr(style), New IntPtr(style)) 
     MyBase.OnHandleCreated(e) 
    End Sub 

    Public Sub SetNodeCheckState(node As TreeNode, state As CheckState) 
     If state = CheckState.Indeterminate Then 
      If System.Environment.OSVersion.Version.Major >= 6 Then 
       Dim it As TV_ITEM = Nothing 
       it.mask = TVIF_HANDLE Or TVIF_STATE 
       it.hItem = node.Handle 
       it.stateMask = TVIS_STATEIMAGEMASK 
       it.state = INDEXTOSTATEIMAGEMASK(3) 'indeterminate 
       SendMessage(Me.Handle, TVM_SETITEM, IntPtr.Zero, it) 
      Else 
       node.Checked = False 
      End If 
     Else 
      node.Checked = (state = CheckState.Checked) 
     End If 
    End Sub 
End Class