Recently I needed to implement multiselect tree view. Knowing that there is nothing new under the sun I googled for solution and found this article. At first glance it worked as expected, however later I had to improve it.
- it does not support editing of text nodes;
- added property for turning off multiselect;
- removed built-in tooltips;
- enabled node selection with clicks in a row, not only on text and icon.
// Disable built-in tooltips protected override CreateParams CreateParams { get { CreateParams parms = base.CreateParams; parms.Style |= 0x80; // Turn on TVS_NOTOOLTIPS return parms; } } // Switch to enable or disable multiselect private bool _multiSelectEnabled; public bool MultiSelectEnabled { get { return _multiSelectEnabled; } set { _multiSelectEnabled = value; //reset selection if (!_multiSelectEnabled && SelectedNodes.Count > 0) SelectedNode = SelectedNodes[0]; } } private Listm_SelectedNodes; public List SelectedNodes { get { return m_SelectedNodes; } set { ClearSelectedNodes(); if (MultiSelectEnabled) { if (value != null) { foreach (TreeNode node in value) { ToggleNode(node, true); } } } else { if (value.Count > 0) { m_SelectedNodes.Clear(); ToggleNode(value[0], true); } } } } // if user clicks on node, we will check if we need to edit nodes text private TreeNode _clickedNode; protected override void OnMouseDown(MouseEventArgs e) { // If the user clicks on a node that was not previously selected, select it now. try { base.SelectedNode = null; TreeNode node = this.GetNodeAt(e.Location); if (node != null) { if (ModifierKeys == Keys.None && (m_SelectedNodes.Contains(node))) { _clickedNode = node; } else { if (MultiSelectEnabled) //if multiselect enabled - SelectNode { SelectNode(node); } else //else select single node { SelectSingleNode(node); } } } base.OnMouseDown(e); } catch (Exception ex) { HandleException(ex); } } protected override void OnMouseUp(MouseEventArgs e) { try { var node = this.GetNodeAt(e.Location); if (node != null && ModifierKeys == Keys.None && m_SelectedNodes.Contains(node)) { if (MultiSelectEnabled) { SelectNode(node); } else { SelectSingleNode(node); } int leftBound = node.Bounds.X; int rightBound = node.Bounds.Right; if (_clickedNode == node && e.Location.X > leftBound && e.Location.X < rightBound) { _clickedNode.BeginEdit(); // single click on node - we can rename it } } _clickedNode = null; //clear clicked node base.OnMouseUp(e); } catch (Exception ex) { HandleException(ex); } }