TreeView节点可以有中间选中状态吗?

4
这是我想做的事情:
- 表示一组按类别划分的选项。 - 允许用户通过选中/取消选中类别节点来选中/取消选中该类别内的所有项目。 - 通过将类别节点设置为中间选中状态,显示某些类别内已选中的选项。
根据我所读的和对TreeView的有限经验,这最后一个期望似乎不可能实现,因为TreeNodes似乎仅支持开/关两种选中状态。使用TreeView是否可以实现此操作?是否有其他控件可以完成此操作,或者我必须制作TreeView的子类才能完成此操作?

嗨,处理TreeView中的“不确定复选框状态”(而不是深入WinForms本机TreeView的“沼泽”,这是一个包装器,非常难以子类化并创建具有自定义“绘画”的所有者绘制版本)是我使用第三方TreeView的原因之一,该TreeView具有您描述的功能。 您可以在此SO帖子上查看我对所使用的TreeView的评论:http://stackoverflow.com/questions/1983600/c-treeview-check-number-of-checked-children/1983715#1983715 - BillW
4个回答

3
您可以使用支持三种状态的自定义TreeView,例如这个,它支持checkBoxes

2

您可以使用DrawMode属性来绘制自己的复选框,方法是使用ControlPaint.DrawCheckBox()。您还需要实现MouseDown事件并使用HitTest方法来检测对虚拟复选框的单击。虽然不是很容易,但这是可能的。


1
这是我针对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

0

我认为你需要自己编写该功能。你可以简单地将复选框颜色设置为浅灰色或其他颜色以显示中间状态。

如果你正在使用WPF,我认为你可以修改TreeView的控件模板和/或复选框的控件模板。

在WPF中,我认为实现这个功能比WinForms更容易。不确定你在这种情况下使用的是什么技术。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接