Added the source code of Aga.Controls (TreeViewAdv for .Net) version 1.7.0.0.
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.ComponentModel;
6 using System.Security.Permissions;
7 using System.Threading;
8 using System.Windows.Forms;
9 using System.Collections;
11 using Aga.Controls.Tree.NodeControls;
12 using Aga.Controls.Threading;
15 namespace Aga.Controls.Tree
18 /// Extensible advanced <see cref="TreeView"/> implemented in 100% managed C# code.
19 /// Features: Model/View architecture. Multiple column per node. Ability to select
20 /// multiple tree nodes. Different types of controls for each node column:
21 /// <see cref="CheckBox"/>, Icon, Label... Drag and Drop highlighting. Load on
22 /// demand of nodes. Incremental search of nodes.
24 public partial class TreeViewAdv : Control
26 private const int LeftMargin = 7;
27 internal const int ItemDragSensivity = 4;
28 private readonly int _columnHeaderHeight;
29 private const int DividerWidth = 9;
30 private const int DividerCorrectionGap = -2;
34 private bool _suspendUpdate;
35 private bool _needFullUpdate;
36 private bool _fireSelectionEvent;
37 private NodePlusMinus _plusMinus;
38 private ToolTip _toolTip;
39 private DrawContext _measureContext;
40 private TreeColumn _hotColumn;
41 private IncrementalSearch _search;
42 private List<TreeNodeAdv> _expandingNodes = new List<TreeNodeAdv>();
43 private AbortableThreadPool _threadPool = new AbortableThreadPool();
48 public event ItemDragEventHandler ItemDrag;
49 private void OnItemDrag(MouseButtons buttons, object item)
52 ItemDrag(this, new ItemDragEventArgs(buttons, item));
55 [Category("Behavior")]
56 public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseClick;
57 private void OnNodeMouseClick(TreeNodeAdvMouseEventArgs args)
59 if (NodeMouseClick != null)
60 NodeMouseClick(this, args);
63 [Category("Behavior")]
64 public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseDoubleClick;
65 private void OnNodeMouseDoubleClick(TreeNodeAdvMouseEventArgs args)
67 if (NodeMouseDoubleClick != null)
68 NodeMouseDoubleClick(this, args);
71 [Category("Behavior")]
72 public event EventHandler<TreeColumnEventArgs> ColumnWidthChanged;
73 internal void OnColumnWidthChanged(TreeColumn column)
75 if (ColumnWidthChanged != null)
76 ColumnWidthChanged(this, new TreeColumnEventArgs(column));
79 [Category("Behavior")]
80 public event EventHandler<TreeColumnEventArgs> ColumnReordered;
81 internal void OnColumnReordered(TreeColumn column)
83 if (ColumnReordered != null)
84 ColumnReordered(this, new TreeColumnEventArgs(column));
87 [Category("Behavior")]
88 public event EventHandler<TreeColumnEventArgs> ColumnClicked;
89 internal void OnColumnClicked(TreeColumn column)
91 if (ColumnClicked != null)
92 ColumnClicked(this, new TreeColumnEventArgs(column));
95 [Category("Behavior")]
96 public event EventHandler SelectionChanged;
97 internal void OnSelectionChanged()
99 if (SuspendSelectionEvent)
100 _fireSelectionEvent = true;
103 _fireSelectionEvent = false;
104 if (SelectionChanged != null)
105 SelectionChanged(this, EventArgs.Empty);
109 [Category("Behavior")]
110 public event EventHandler<TreeViewAdvEventArgs> Collapsing;
111 private void OnCollapsing(TreeNodeAdv node)
113 if (Collapsing != null)
114 Collapsing(this, new TreeViewAdvEventArgs(node));
117 [Category("Behavior")]
118 public event EventHandler<TreeViewAdvEventArgs> Collapsed;
119 private void OnCollapsed(TreeNodeAdv node)
121 if (Collapsed != null)
122 Collapsed(this, new TreeViewAdvEventArgs(node));
125 [Category("Behavior")]
126 public event EventHandler<TreeViewAdvEventArgs> Expanding;
127 private void OnExpanding(TreeNodeAdv node)
129 if (Expanding != null)
130 Expanding(this, new TreeViewAdvEventArgs(node));
133 [Category("Behavior")]
134 public event EventHandler<TreeViewAdvEventArgs> Expanded;
135 private void OnExpanded(TreeNodeAdv node)
137 if (Expanded != null)
138 Expanded(this, new TreeViewAdvEventArgs(node));
141 [Category("Behavior")]
142 public event EventHandler GridLineStyleChanged;
143 private void OnGridLineStyleChanged()
145 if (GridLineStyleChanged != null)
146 GridLineStyleChanged(this, EventArgs.Empty);
149 [Category("Behavior")]
150 public event ScrollEventHandler Scroll;
151 protected virtual void OnScroll(ScrollEventArgs e)
157 [Category("Behavior")]
158 public event EventHandler<TreeViewRowDrawEventArgs> RowDraw;
159 protected virtual void OnRowDraw(PaintEventArgs e, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect)
163 TreeViewRowDrawEventArgs args = new TreeViewRowDrawEventArgs(e.Graphics, e.ClipRectangle, node, context, row, rowRect);
169 /// Fires when control is going to draw. Can be used to change text or back color
171 [Category("Behavior")]
172 public event EventHandler<DrawEventArgs> DrawControl;
174 internal bool DrawControlMustBeFired()
176 return DrawControl != null;
179 internal void FireDrawControl(DrawEventArgs args)
184 protected virtual void OnDrawControl(DrawEventArgs args)
186 if (DrawControl != null)
187 DrawControl(this, args);
191 [Category("Drag Drop")]
192 public event EventHandler<DropNodeValidatingEventArgs> DropNodeValidating;
193 protected virtual void OnDropNodeValidating(Point point, ref TreeNodeAdv node)
195 if (DropNodeValidating != null)
197 DropNodeValidatingEventArgs args = new DropNodeValidatingEventArgs(point, node);
198 DropNodeValidating(this, args);
206 InitializeComponent();
207 SetStyle(ControlStyles.AllPaintingInWmPaint
208 | ControlStyles.UserPaint
209 | ControlStyles.OptimizedDoubleBuffer
210 | ControlStyles.ResizeRedraw
211 | ControlStyles.Selectable
215 if (Application.RenderWithVisualStyles)
216 _columnHeaderHeight = 20;
218 _columnHeaderHeight = 17;
220 //BorderStyle = BorderStyle.Fixed3D;
221 _hScrollBar.Height = SystemInformation.HorizontalScrollBarHeight;
222 _vScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
223 _rowLayout = new FixedRowHeightLayout(this, RowHeight);
224 _rowMap = new List<TreeNodeAdv>();
225 _selection = new List<TreeNodeAdv>();
226 _readonlySelection = new ReadOnlyCollection<TreeNodeAdv>(_selection);
227 _columns = new TreeColumnCollection(this);
228 _toolTip = new ToolTip();
230 _measureContext = new DrawContext();
231 _measureContext.Font = Font;
232 _measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1));
234 Input = new NormalInputState(this);
235 _search = new IncrementalSearch(this);
241 _plusMinus = new NodePlusMinus();
242 _controls = new NodeControlsCollection(this);
245 ExpandingIcon.IconChanged += ExpandingIconChanged;
248 void ExpandingIconChanged(object sender, EventArgs e)
250 if (IsHandleCreated && !IsDisposed)
251 BeginInvoke(new MethodInvoker(DrawIcons));
254 private void DrawIcons()
256 using (Graphics gr = Graphics.FromHwnd(this.Handle))
258 //Apply the same Graphics Transform logic as used in OnPaint.
262 y += ColumnHeaderHeight;
263 if (Columns.Count == 0)
266 int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
269 gr.TranslateTransform(-OffsetX, y);
271 DrawContext context = new DrawContext();
272 context.Graphics = gr;
273 for (int i = 0; i < _expandingNodes.Count; i++)
275 foreach (NodeControlInfo item in GetNodeControls(_expandingNodes[i]))
277 if (item.Control is ExpandingIcon)
279 Rectangle bounds = item.Bounds;
280 if (item.Node.Parent == null && UseColumns)
281 bounds.Location = Point.Empty; // display root expanding icon at 0,0
283 context.Bounds = bounds;
284 item.Control.Draw(item.Node, context);
291 #region Public Methods
293 public TreePath GetPath(TreeNodeAdv node)
296 return TreePath.Empty;
299 Stack<object> stack = new Stack<object>();
300 while (node != _root && node != null)
302 stack.Push(node.Tag);
305 return new TreePath(stack.ToArray());
309 public TreeNodeAdv GetNodeAt(Point point)
311 NodeControlInfo info = GetNodeControlInfoAt(point);
315 public NodeControlInfo GetNodeControlInfoAt(Point point)
317 if (point.X < 0 || point.Y < 0)
318 return NodeControlInfo.Empty;
320 int row = _rowLayout.GetRowAt(point);
321 if (row < RowCount && row >= 0)
322 return GetNodeControlInfoAt(RowMap[row], point);
324 return NodeControlInfo.Empty;
327 private NodeControlInfo GetNodeControlInfoAt(TreeNodeAdv node, Point point)
329 Rectangle rect = _rowLayout.GetRowBounds(FirstVisibleRow);
330 point.Y += (rect.Y - ColumnHeaderHeight);
332 foreach (NodeControlInfo info in GetNodeControls(node))
333 if (info.Bounds.Contains(point))
337 return new NodeControlInfo(null, Rectangle.Empty, node);
339 return NodeControlInfo.Empty;
342 public void BeginUpdate()
344 _suspendUpdate = true;
345 SuspendSelectionEvent = true;
348 public void EndUpdate()
350 _suspendUpdate = false;
355 SuspendSelectionEvent = false;
358 public void ExpandAll()
363 public void CollapseAll()
369 /// Expand all parent nodes, andd scroll to the specified node
371 public void EnsureVisible(TreeNodeAdv node)
374 throw new ArgumentNullException("node");
377 throw new ArgumentException();
379 TreeNodeAdv parent = node.Parent;
380 while (parent != _root)
382 parent.IsExpanded = true;
383 parent = parent.Parent;
389 /// Make node visible, scroll if needed. All parent nodes of the specified node must be expanded
391 /// <param name="node"></param>
392 public void ScrollTo(TreeNodeAdv node)
395 throw new ArgumentNullException("node");
398 throw new ArgumentException();
405 if (node.Row < FirstVisibleRow)
409 int pageStart = _rowLayout.GetRowBounds(FirstVisibleRow).Top;
410 int rowBottom = _rowLayout.GetRowBounds(node.Row).Bottom;
411 if (rowBottom > pageStart + DisplayRectangle.Height - ColumnHeaderHeight)
412 row = _rowLayout.GetFirstRow(node.Row);
415 if (row >= _vScrollBar.Minimum && row <= _vScrollBar.Maximum)
416 _vScrollBar.Value = row;
419 public void ClearSelection()
424 ClearSelectionInternal();
432 internal void ClearSelectionInternal()
434 while (Selection.Count > 0)
436 var t = Selection[0];
437 t.IsSelected = false;
438 Selection.Remove(t); //hack
444 protected override void OnSizeChanged(EventArgs e)
447 SafeUpdateScrollBars();
448 base.OnSizeChanged(e);
451 private void ArrangeControls()
453 int hBarSize = _hScrollBar.Height;
454 int vBarSize = _vScrollBar.Width;
455 Rectangle clientRect = ClientRectangle;
457 _hScrollBar.SetBounds(clientRect.X, clientRect.Bottom - hBarSize,
458 clientRect.Width - vBarSize, hBarSize);
460 _vScrollBar.SetBounds(clientRect.Right - vBarSize, clientRect.Y,
461 vBarSize, clientRect.Height - hBarSize);
464 private void SafeUpdateScrollBars()
467 BeginInvoke(new MethodInvoker(UpdateScrollBars));
472 private void UpdateScrollBars()
478 _hScrollBar.Width = DisplayRectangle.Width;
479 _vScrollBar.Height = DisplayRectangle.Height;
482 private void UpdateHScrollBar()
484 _hScrollBar.Maximum = ContentWidth;
485 _hScrollBar.LargeChange = Math.Max(DisplayRectangle.Width, 0);
486 _hScrollBar.SmallChange = 5;
487 _hScrollBar.Visible = _hScrollBar.LargeChange < _hScrollBar.Maximum;
488 _hScrollBar.Value = Math.Min(_hScrollBar.Value, _hScrollBar.Maximum - _hScrollBar.LargeChange + 1);
491 private void UpdateVScrollBar()
493 _vScrollBar.Maximum = Math.Max(RowCount - 1, 0);
494 _vScrollBar.LargeChange = _rowLayout.PageRowCount;
495 _vScrollBar.Visible = (RowCount > 0) && (_vScrollBar.LargeChange <= _vScrollBar.Maximum);
496 _vScrollBar.Value = Math.Min(_vScrollBar.Value, _vScrollBar.Maximum - _vScrollBar.LargeChange + 1);
499 protected override CreateParams CreateParams
501 [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
504 CreateParams res = base.CreateParams;
507 case BorderStyle.FixedSingle:
508 res.Style |= 0x800000;
510 case BorderStyle.Fixed3D:
511 res.ExStyle |= 0x200;
518 protected override void OnGotFocus(EventArgs e)
525 protected override void OnFontChanged(EventArgs e)
527 base.OnFontChanged(e);
528 _measureContext.Font = Font;
532 internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node)
536 Rectangle rowRect = _rowLayout.GetRowBounds(node.Row);
537 foreach (NodeControlInfo n in GetNodeControls(node, rowRect))
541 internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node, Rectangle rowRect)
547 int x = (node.Level - 1) * _indent + LeftMargin;
549 if (node.Row == 0 && ShiftFirstNode)
551 Rectangle rect = Rectangle.Empty;
555 width = _plusMinus.GetActualSize(node, _measureContext).Width;
556 rect = new Rectangle(x, y, width, rowRect.Height);
557 if (UseColumns && Columns.Count > 0 && Columns[0].Width < rect.Right)
558 rect.Width = Columns[0].Width - x;
560 yield return new NodeControlInfo(_plusMinus, rect, node);
566 foreach (NodeControl c in NodeControls)
568 Size s = c.GetActualSize(node, _measureContext);
572 rect = new Rectangle(x, y, width, rowRect.Height);
574 yield return new NodeControlInfo(c, rect, node);
581 foreach (TreeColumn col in Columns)
583 if (col.IsVisible && col.Width > 0)
586 for (int i = 0; i < NodeControls.Count; i++)
588 NodeControl nc = NodeControls[i];
589 if (nc.ParentColumn == col)
591 Size s = nc.GetActualSize(node, _measureContext);
594 bool isLastControl = true;
595 for (int k = i + 1; k < NodeControls.Count; k++)
596 if (NodeControls[k].ParentColumn == col)
598 isLastControl = false;
605 int maxWidth = Math.Max(0, right - x);
606 rect = new Rectangle(x, y, Math.Min(maxWidth, width), rowRect.Height);
608 yield return new NodeControlInfo(nc, rect, node);
618 internal static double Dist(Point p1, Point p2)
620 return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
623 public void FullUpdate()
627 BeginInvoke(new MethodInvoker(UnsafeFullUpdate));
632 private void UnsafeFullUpdate()
634 _rowLayout.ClearCache();
636 SafeUpdateScrollBars();
638 _needFullUpdate = false;
641 internal void UpdateView()
647 internal void UpdateHeaders()
649 Invalidate(new Rectangle(0, 0, Width, ColumnHeaderHeight));
652 internal void UpdateColumns()
657 private void CreateNodes()
660 SelectionStart = null;
661 _root = new TreeNodeAdv(this, null);
662 _root.IsExpanded = true;
663 if (_root.Nodes.Count > 0)
664 CurrentNode = _root.Nodes[0];
669 internal void ReadChilds(TreeNodeAdv parentNode)
671 ReadChilds(parentNode, false);
674 internal void ReadChilds(TreeNodeAdv parentNode, bool performFullUpdate)
676 if (!parentNode.IsLeaf)
678 parentNode.IsExpandedOnce = true;
679 parentNode.Nodes.Clear();
683 IEnumerable items = Model.GetChildren(GetPath(parentNode));
685 foreach (object obj in items)
687 AddNewNode(parentNode, obj, -1);
688 if (performFullUpdate)
693 if (parentNode.AutoExpandOnStructureChanged)
694 parentNode.ExpandAll();
698 private void AddNewNode(TreeNodeAdv parent, object tag, int index)
700 TreeNodeAdv node = new TreeNodeAdv(this, tag);
701 AddNode(parent, index, node);
704 private void AddNode(TreeNodeAdv parent, int index, TreeNodeAdv node)
706 if (index >= 0 && index < parent.Nodes.Count)
707 parent.Nodes.Insert(index, node);
709 parent.Nodes.Add(node);
711 node.IsLeaf = Model.IsLeaf(GetPath(node));
714 if (!LoadOnDemand || node.IsExpandedOnce)
718 private struct ExpandArgs
720 public TreeNodeAdv Node;
722 public bool IgnoreChildren;
725 public void AbortBackgroundExpandingThreads()
727 _threadPool.CancelAll(true);
728 for (int i = 0; i < _expandingNodes.Count; i++)
729 _expandingNodes[i].IsExpandingNow = false;
730 _expandingNodes.Clear();
734 internal void SetIsExpanded(TreeNodeAdv node, bool value, bool ignoreChildren)
736 ExpandArgs eargs = new ExpandArgs();
739 eargs.IgnoreChildren = ignoreChildren;
741 if (AsyncExpanding && LoadOnDemand && !_threadPool.IsMyThread(Thread.CurrentThread))
743 WaitCallback wc = delegate(object argument) { SetIsExpanded((ExpandArgs)argument); };
744 _threadPool.QueueUserWorkItem(wc, eargs);
747 SetIsExpanded(eargs);
750 private void SetIsExpanded(ExpandArgs eargs)
752 bool update = !eargs.IgnoreChildren && !AsyncExpanding;
757 if (IsMyNode(eargs.Node) && eargs.Node.IsExpanded != eargs.Value)
758 SetIsExpanded(eargs.Node, eargs.Value);
760 if (!eargs.IgnoreChildren)
761 SetIsExpandedRecursive(eargs.Node, eargs.Value);
770 internal void SetIsExpanded(TreeNodeAdv node, bool value)
772 if (Root == node && !value)
773 return; //Can't collapse root node
786 if (value && !node.IsExpandedOnce)
788 if (AsyncExpanding && LoadOnDemand)
790 AddExpandingNode(node);
791 node.AssignIsExpanded(true);
794 ReadChilds(node, AsyncExpanding);
795 RemoveExpandingNode(node);
797 node.AssignIsExpanded(value);
812 private void RemoveExpandingNode(TreeNodeAdv node)
814 node.IsExpandingNow = false;
815 _expandingNodes.Remove(node);
816 if (_expandingNodes.Count <= 0)
817 ExpandingIcon.Stop();
820 private void AddExpandingNode(TreeNodeAdv node)
822 node.IsExpandingNow = true;
823 _expandingNodes.Add(node);
824 ExpandingIcon.Start();
827 internal void SetIsExpandedRecursive(TreeNodeAdv root, bool value)
829 for (int i = 0; i < root.Nodes.Count; i++)
831 TreeNodeAdv node = root.Nodes[i];
832 node.IsExpanded = value;
833 SetIsExpandedRecursive(node, value);
837 private void CreateRowMap()
842 foreach (TreeNodeAdv node in VisibleNodes)
848 _contentWidth = Math.Max(_contentWidth, GetNodeWidth(node));
855 foreach (TreeColumn col in _columns)
857 _contentWidth += col.Width;
861 private int GetNodeWidth(TreeNodeAdv node)
863 if (node.RightBounds == null)
865 Rectangle res = GetNodeBounds(GetNodeControls(node, Rectangle.Empty));
866 node.RightBounds = res.Right;
868 return node.RightBounds.Value;
871 internal Rectangle GetNodeBounds(TreeNodeAdv node)
873 return GetNodeBounds(GetNodeControls(node));
876 private Rectangle GetNodeBounds(IEnumerable<NodeControlInfo> nodeControls)
878 Rectangle res = Rectangle.Empty;
879 foreach (NodeControlInfo info in nodeControls)
881 if (res == Rectangle.Empty)
884 res = Rectangle.Union(res, info.Bounds);
889 private void _vScrollBar_ValueChanged(object sender, EventArgs e)
891 FirstVisibleRow = _vScrollBar.Value;
894 private void _hScrollBar_ValueChanged(object sender, EventArgs e)
896 OffsetX = _hScrollBar.Value;
899 private void _vScrollBar_Scroll(object sender, ScrollEventArgs e)
904 private void _hScrollBar_Scroll(object sender, ScrollEventArgs e)
909 internal void SmartFullUpdate()
912 _needFullUpdate = true;
917 internal bool IsMyNode(TreeNodeAdv node)
922 if (node.Tree != this)
925 while (node.Parent != null)
928 return node == _root;
931 internal void UpdateSelection()
935 if (!IsMyNode(CurrentNode))
937 if (!IsMyNode(_selectionStart))
938 _selectionStart = null;
940 for (int i = Selection.Count - 1; i >= 0; i--)
941 if (!IsMyNode(Selection[i]))
944 Selection.RemoveAt(i);
948 OnSelectionChanged();
951 internal void ChangeColumnWidth(TreeColumn column)
953 if (!(_input is ResizeColumnState))
956 OnColumnWidthChanged(column);
960 public TreeNodeAdv FindNode(TreePath path)
962 return FindNode(path, false);
965 public TreeNodeAdv FindNode(TreePath path, bool readChilds)
970 return FindNode(_root, path, 0, readChilds);
973 private TreeNodeAdv FindNode(TreeNodeAdv root, TreePath path, int level, bool readChilds)
975 if (!root.IsExpandedOnce && readChilds)
978 for (int i = 0; i < root.Nodes.Count; i++)
980 TreeNodeAdv node = root.Nodes[i];
981 if (node.Tag == path.FullPath[level])
983 if (level == path.FullPath.Length - 1)
986 return FindNode(node, path, level + 1, readChilds);
992 public TreeNodeAdv FindNodeByTag(object tag)
994 return FindNodeByTag(_root, tag);
997 private TreeNodeAdv FindNodeByTag(TreeNodeAdv root, object tag)
999 foreach (TreeNodeAdv node in root.Nodes)
1001 if (node.Tag == tag)
1003 TreeNodeAdv res = FindNodeByTag(node, tag);
1010 public void SelectAllNodes()
1012 SuspendSelectionEvent = true;
1015 if (SelectionMode == TreeSelectionMode.MultiSameParent)
1017 if (CurrentNode != null)
1019 foreach (TreeNodeAdv n in CurrentNode.Parent.Nodes)
1020 n.IsSelected = true;
1023 else if (SelectionMode == TreeSelectionMode.Multi)
1025 SelectNodes(Root.Nodes);
1030 SuspendSelectionEvent = false;
1034 private void SelectNodes(Collection<TreeNodeAdv> nodes)
1036 foreach (TreeNodeAdv n in nodes)
1038 n.IsSelected = true;
1040 SelectNodes(n.Nodes);
1045 private void BindModelEvents()
1047 _model.NodesChanged += new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1048 _model.NodesInserted += new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1049 _model.NodesRemoved += new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1050 _model.StructureChanged += new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1053 private void UnbindModelEvents()
1055 _model.NodesChanged -= new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1056 _model.NodesInserted -= new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1057 _model.NodesRemoved -= new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1058 _model.StructureChanged -= new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1061 private void _model_StructureChanged(object sender, TreePathEventArgs e)
1064 throw new ArgumentNullException();
1066 TreeNodeAdv node = FindNode(e.Path);
1070 node.IsLeaf = Model.IsLeaf(GetPath(node));
1072 var list = new Dictionary<object, object>();
1073 SaveExpandedNodes(node, list);
1075 RestoreExpandedNodes(node, list);
1081 // throw new ArgumentException("Path not found");
1084 private void RestoreExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1086 if (node.Tag != null && list.ContainsKey(node.Tag))
1088 node.IsExpanded = true;
1089 foreach (var child in node.Children)
1090 RestoreExpandedNodes(child, list);
1094 private void SaveExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1096 if (node.IsExpanded && node.Tag != null)
1098 list.Add(node.Tag, null);
1099 foreach (var child in node.Children)
1100 SaveExpandedNodes(child, list);
1104 private void _model_NodesRemoved(object sender, TreeModelEventArgs e)
1106 TreeNodeAdv parent = FindNode(e.Path);
1109 if (e.Indices != null)
1111 List<int> list = new List<int>(e.Indices);
1113 for (int n = list.Count - 1; n >= 0; n--)
1115 int index = list[n];
1116 if (index >= 0 && index <= parent.Nodes.Count)
1117 parent.Nodes.RemoveAt(index);
1119 throw new ArgumentOutOfRangeException("Index out of range");
1124 for (int i = parent.Nodes.Count - 1; i >= 0; i--)
1126 for (int n = 0; n < e.Children.Length; n++)
1127 if (parent.Nodes[i].Tag == e.Children[n])
1129 parent.Nodes.RemoveAt(i);
1139 private void _model_NodesInserted(object sender, TreeModelEventArgs e)
1141 if (e.Indices == null)
1142 throw new ArgumentNullException("Indices");
1144 TreeNodeAdv parent = FindNode(e.Path);
1147 for (int i = 0; i < e.Children.Length; i++)
1148 AddNewNode(parent, e.Children[i], e.Indices[i]);
1153 private void _model_NodesChanged(object sender, TreeModelEventArgs e)
1155 TreeNodeAdv parent = FindNode(e.Path);
1156 if (parent != null && parent.IsVisible && parent.IsExpanded)
1159 BeginInvoke(new UpdateContentWidthDelegate(ClearNodesSize), e, parent);
1161 ClearNodesSize(e, parent);
1166 private delegate void UpdateContentWidthDelegate(TreeModelEventArgs e, TreeNodeAdv parent);
1167 private void ClearNodesSize(TreeModelEventArgs e, TreeNodeAdv parent)
1169 if (e.Indices != null)
1171 foreach (int index in e.Indices)
1173 if (index >= 0 && index < parent.Nodes.Count)
1175 TreeNodeAdv node = parent.Nodes[index];
1176 node.Height = node.RightBounds = null;
1179 throw new ArgumentOutOfRangeException("Index out of range");
1184 foreach (TreeNodeAdv node in parent.Nodes)
1186 foreach (object obj in e.Children)
1187 if (node.Tag == obj)
1189 node.Height = node.RightBounds = null;