2010-01-06 71 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