protected override void OnBeforeSelect(TreeViewCancelEventArgs e) { base.OnBeforeSelect(e); // New selection is always the anchor for the next shift selection if (_anchorNode == null || !IsRangeSelect) { _anchorNode = (TreeNodeMS)e.Node; } }
protected override void OnAfterSelect(TreeViewEventArgs e) { // Save old selection for invalidating var selectedNodesOld = SelectedNodes.ToArray(); TreeNodeMS node = (TreeNodeMS)e.Node; // Don't change the selection if this is a right click and the node is in the // selection. if (node != null && !(_inRightClick && node.IsInSelection)) { if (IsDisjointSelect) { // Toggle selection on the node SelectNode(node, !IsNodeSelected(e.Node)); } else if (IsRangeSelect && !ReferenceEquals(_anchorNode, node)) { // Figure out top and bottom of the range to be selected TreeNodeMS upperNode = _anchorNode; TreeNodeMS bottomNode = node; if (upperNode.BoundsMS.Top > bottomNode.BoundsMS.Top) { Helpers.Swap(ref upperNode, ref bottomNode); } // Set new selection to contain all visible nodes between top and bottom SelectedNodes.Clear(); while (upperNode != null && !ReferenceEquals(upperNode, bottomNode)) { SelectNode(upperNode, true); upperNode = (TreeNodeMS)upperNode.NextVisibleNode; } SelectNode(bottomNode, true); } else { // Make this a single selection of the selected node. SelectedNodes.Clear(); SelectNode(node, true); } // Invalidate the changed nodes var unchangedNodes = new HashSet <TreeNodeMS>(selectedNodesOld.Intersect(SelectedNodes)); InvalidateChangedNodes(selectedNodesOld, unchangedNodes); InvalidateChangedNodes(SelectedNodes, unchangedNodes); } Invalidate(); // Make sure selection is updated before after select event is fired base.OnAfterSelect(e); }
protected override void OnMouseDown(MouseEventArgs e) { _inRightClick = e.Button == MouseButtons.Right; if (_inRightClick) { TreeNodeMS node = (TreeNodeMS)GetNodeAt(0, e.Y); if (node != null && node.BoundsMS.Contains(e.Location)) { SelectedNode = node; } } base.OnMouseDown(e); }
public void SelectNode(TreeNodeMS node, bool select) { if (!select) { SelectedNodes.Remove(node); } else if (!node.IsInSelection) { SelectedNodes.Add(node); // Make sure all ancestors of this node are expanded for (var parent = node.Parent; parent != null && !parent.IsExpanded; parent = parent.Parent) { parent.Expand(); } } node.IsInSelection = select; }
protected void UpdateSelection() { // Remove any nodes from the selection that may have been // removed from the tree. var selectedNodes = SelectedNodes.ToArray(); foreach (var node in selectedNodes) { if (node.TreeView == null) { SelectedNodes.Remove(node); } } // If any nodes were removed from the selection, reset the // anchor node to the selected node. if (selectedNodes.Length != SelectedNodes.Count) { _anchorNode = (TreeNodeMS)SelectedNode; } }
protected override void OnMouseUp(MouseEventArgs e) { if (!_inRightClick) { TreeNodeMS node = (TreeNodeMS)GetNodeAt(0, e.Y); if (node != null && node.BoundsMS.Contains(e.Location)) { // If we are within the bounds of a node and that node is not the selected node, // make it the selected node. Changing the font of the TreeView at runtime // apparently does not update node bounds, so we need to do this check in case the // user clicked outside of the original node bounds. if (!ReferenceEquals(node, SelectedNode)) { SelectedNode = node; } // Handle cases where clicking on the selected node should change // the selection. else { // Disjoint selection or the SelectedNode is not in the selection if (IsDisjointSelect || !IsNodeSelected(node)) { SelectedNode = null; } // More than a single node currently selected, and not performing // range selection on an existing range selection. else if (SelectedNodes.Count > 1 && (!IsRangeSelect || ReferenceEquals(_anchorNode, SelectedNode))) { SelectedNode = null; } } } } base.OnMouseUp(e); _inRightClick = false; }
public virtual void DrawNodeCustom(Graphics g, int rightEdge) { EnsureWidthCustom(g); Rectangle bounds = BoundsMS; // Draw dashed lines var treeView = TreeViewMS; var dashBrush = treeView.DashBrush; // Horizontal line. dashBrush.TranslateTransform(Level % 2 + HorizScrollDiff, 0); g.FillRectangle(dashBrush, XIndent, bounds.Top + bounds.Height / 2, TreeViewMS.HORZ_DASH_LENGTH, 1); // Vertical lines corresponding to the horizontal level of this node. dashBrush.TranslateTransform(-Level % 2 - HorizScrollDiff, 0); // Check if this is the Root. if (ReferenceEquals(this, treeView.Nodes[0])) { if (treeView.Nodes.Count > 1) { g.FillRectangle(dashBrush, XIndent, bounds.Top + bounds.Height / 2, 1, bounds.Height / 2); } } // Move up the levels of the tree, drawing the corresponding vertical lines. else { try { TreeNodeMS curNode = this; while (curNode != null) { dashBrush.TranslateTransform(0, curNode.Level % 2); if (curNode.NextNode != null) { g.FillRectangle(dashBrush, curNode.XIndent, bounds.Top, 1, bounds.Height); } else if (curNode == this) { g.FillRectangle(dashBrush, curNode.XIndent, bounds.Top, 1, bounds.Height / 2); } dashBrush.TranslateTransform(0, -curNode.Level % 2); curNode = curNode.Parent as TreeNodeMS; } } catch (NullReferenceException) { // Ignore a NullReferenceException in this code. The case // that once caused this has been fixed, but this safeguard is // kept to avoid showing an unhandled exception to the user. // If the node being painted is in the process of being removed // from the tree, then curNode.NextNode will throw a NRE. } } // Draw Collapse/Expand bmps and the image associated with the node. if (Nodes.Count > 0) { Image expandCollapse = IsExpanded ? Resources.Collapse : Resources.Expand; g.DrawImage(expandCollapse, XIndent - expandCollapse.Width / 2, bounds.Top + (BoundsMS.Height - expandCollapse.Height + 1) / 2); } // Draw images associated with the node. int imgLocX = XIndent + TreeViewMS.HORZ_DASH_LENGTH; const int imgWidth = TreeViewMS.IMG_WIDTH, imgHeight = TreeViewMS.IMG_WIDTH; if (StateImageIndex != -1) { Image stateImg = TreeView.StateImageList.Images[StateImageIndex]; g.DrawImageUnscaled(stateImg, imgLocX, bounds.Top + (bounds.Height - imgHeight) / 2, imgWidth, imgHeight); imgLocX += imgWidth; } if (ImageIndex != -1) { Image nodeImg = TreeView.ImageList.Images[ImageIndex]; g.DrawImageUnscaled(nodeImg, imgLocX, bounds.Top + (bounds.Height - imgHeight) / 2, imgWidth, imgHeight); } DrawTextMS(g); }
protected void InvalidateNode(TreeNodeMS node) { Invalidate(new Rectangle(0, node.BoundsMS.Top, ClientRectangle.Width, node.BoundsMS.Height)); }