Can TreeView nodes have intermediate checked states?

Here is what I want to do:

  • Represents a set of options, categorized.
  • Allow the user to check / uncheck all elements in the category by checking / unchecking the node category.
  • Show that some parameters in the category are checked by setting the node category to an intermediate controlled state.

From what I read and my limited experience with TreeViews, this last wish is not possible, as TreeNodes do not seem to support anything other than an on / off state. Is it possible to use TreeView? Is there some other control that could take this off, or will I have to subclass the TreeView class to do this?

+3
source share
4 answers

This can be done using the DrawMode property so that you can draw your own checkbox using ControlPaint.DrawCheckBox (). You will also have to implement the MouseDown event and use the HitTest method to detect clicks on the fake checkbox. There is not much joy, but it is possible.

+2
source

You can use a custom one that TreeViewsupports three states checkBoxes, like this one .

+1
source

, . - -, .

If you are using WPF, I think you can change the tree structure management template and / or the control template of this checkbox.

In WPF, I would say that it would be easier to implement winforms then. Not sure which technology you are using in this case.

0
source

This is my form of solution for Windows Vista and higher:

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
source

Source: https://habr.com/ru/post/1727437/


All Articles