public override void Dispose() { if (this.node != null && this.node.childIndex != -1) { this.node.ReleaseExternalReference(); this.node = null; } }
static TreeGridNode FindFirstCollapsePoint(TreeGridNode node) { TreeGridNode parentCollapsePoint = null; if (node.level > 1) { Debug.Assert(node.Parent != null, "Node level is wrong in FindFirstCollapsePoint!"); parentCollapsePoint = FindFirstCollapsePoint(node.Parent); } if (node.IsExpanded || (parentCollapsePoint != null)) { // We're expanded, or our parent has a collapse point. If we're expanded // then it's okay if our parent doesn't have a collapsed parent (since we // don't either in that case). return parentCollapsePoint; } // We're collapsed, and either have no parent, or our parent has no collapse point. // We're it. return node; }
static TreeGridNode FindLastNode(TreeGridNode node) { if (node.IsExpanded && node.items != null && node.items.Count > 0) { var lastChild = node.GetOrCreateChildNode(node.items.Count - 1); return FindLastNode(lastChild); } return node; }
public override bool MoveToParentNode() { if (this.node == null) { return false; } TreeGridNode parentNode = this.node.Parent; // Can't move up to root node... if (parentNode is ChildTreeGridNode) { parentNode.AddExternalReference(); this.node.ReleaseExternalReference(); this.node = parentNode; return true; } return false; }
public override bool MoveToFirstCollapsePoint() { if (this.node == null) { return false; } TreeGridNode collapsePoint = FindFirstCollapsePoint(this.node); if (collapsePoint == this.node || collapsePoint == null) { // Didn't move return false; } collapsePoint.AddExternalReference(); this.node.ReleaseExternalReference(); this.node = collapsePoint; return true; }
internal void OnChildCountChanged(TreeGridNode child, int oldCount) { this.ItemCount = this.rootNode.FlatCount; this.VerticalScrollRange = this.ItemCount - 1; // When nodes collapse, it's possible to "swallow" the current node. If that happens, we need // to move the current node up to it's "collapse point" -- the last (downward) exposed node in its heritage. if (this.currentNode != null) { if (this.currentNode.MoveToFirstCollapsePoint()) { RaiseCurrentItemChanged(); } } // Don't do anything if we haven't had our template applied yet... if (this.canvas != null) { if (this.TopItemIndex >= this.ItemCount) { // A collapse-all, filter, or similar operation could cause this. Do a bottom-up // (and therefore synchronous) layout. this.TopItemIndex = Math.Max(0, this.ItemCount - 1); this.bottomUpLayout = true; DoRowLayout(); } else { InvalidateRowLayout(false); } } }
public override bool MoveToChildItemNode(object item) { if (this.node == null) { return false; } this.node.EnsureItems(); int index = this.node.items.IndexOf(item); if (index == -1) { return false; } var nextNode = this.node.GetOrCreateChildNode(index); nextNode.AddExternalReference(); this.node.ReleaseExternalReference(); this.node = nextNode; return true; }
public override void ExpandParents() { if (this.node == null) { return; } for (var node = this.node.Parent; node != null && node.Parent != null; node = node.Parent) { if (!node.IsExpanded) { node.Parent.ToggleChildExpansion(node); } } }
public override bool MoveToNextFlatNode() { if (this.node == null) { return false; } TreeGridNode nextNode = this.node; if (nextNode.IsExpanded && nextNode.items.Count > 0) { // We're on a node that is expanded. Move to its first child. nextNode = nextNode.GetOrCreateChildNode(0); } else { while (nextNode.Parent == null || nextNode.childIndex == nextNode.Parent.items.Count - 1) { // Reached the end of this node. Pop up a level. If we're already at the top, we're done. if (nextNode.Parent == null) { return false; } nextNode = nextNode.Parent; } nextNode = nextNode.Parent.GetOrCreateChildNode(nextNode.childIndex + 1); } nextNode.AddExternalReference(); this.node.ReleaseExternalReference(); this.node = nextNode; return true; }
void OnChildFinalRelease(TreeGridNode child) { if (this.childNodes != null && this.childNodes.ContainsKey(child.childIndex)) { this.childNodes.Remove(child.childIndex); if (this.childNodes.Count == 0 && this.externalReferences == 0 && !this.IsExpanded) { if (this.Parent != null) { this.Parent.OnChildFinalRelease(this); } } } else { Debug.Fail("Final release called; child not found in parent."); } }
public Reference(TreeGridNode node) { this.node = node; Debug.Assert(node != null, "You cannot create a reference to a null node."); Debug.Assert(this.node.Parent != null, "You cannot create a reference to the root node."); this.node.AddExternalReference(); }
void OnChildCountChanged(TreeGridNode child, int oldCount) { int ourOldCount = this.flatCount; this.flatCount = this.flatCount - oldCount + child.flatCount; if (this.IsExpanded) { NotifyParentChildCountChanged(this, ourOldCount); } }
protected virtual void NotifyParentChildCountChanged(TreeGridNode child, int oldCount) { if (!this.IsSuppressingChildCountNotification) { // If this.Parent is null, then there's a parenting problem -- the root node overrides this method. this.Parent.OnChildCountChanged(child, oldCount); } }
void ToggleChildExpansion(TreeGridNode childNode) { int oldFlatCount = this.flatCount; Debug.Assert(childNode.Parent == this, "Expanding a child node that isn't a child?"); if (childNode.IsExpanded) { this.flatCount -= childNode.flatCount; childNode.IsExpanded = false; } else { childNode.EnsureItems(); this.flatCount += childNode.flatCount; childNode.IsExpanded = true; } if (this.IsExpanded) { NotifyParentChildCountChanged(this, oldFlatCount); } if (!childNode.IsExpanded) { // Collapsing a node may be its final reference release if ((childNode.childNodes == null || childNode.childNodes.Count == 0) && childNode.externalReferences == 0) { OnChildFinalRelease(childNode); } } }
internal ChildTreeGridNode(TreeGridNode parent) { this.parent = parent; }
public override bool MoveToPreviousFlatNode() { if (this.node == null) { return false; } TreeGridNode nextNode = this.node; if (this.node.childIndex == 0) { // We're at the top of this list of children. Pop up to the parent if we have one. if (this.node.Parent is RootTreeGridNode) { return false; } nextNode = this.node.Parent; } else { nextNode = this.node.Parent.GetOrCreateChildNode(this.node.childIndex - 1); nextNode = FindLastNode(nextNode); } nextNode.AddExternalReference(); this.node.ReleaseExternalReference(); this.node = nextNode; return true; }
protected override void NotifyParentChildCountChanged(TreeGridNode child, int oldCount) { if (!this.IsSuppressingChildCountNotification) { this.owner.OnChildCountChanged(this, oldCount); } }
public TreeGrid() { this.columns = new ObservableCollection<TreeGridColumn>(); this.columns.CollectionChanged += OnColumnsChanged; // HasChildrenFunc is an optimization opportunity for data sets whose children require computation. this.hasChildrenFunc = DefaultHasChildren; this.childrenFunc = DefaultChildren; this.items = null; this.headerRow = new TreeGridRow(this, true); Canvas.SetTop(this.headerRow, 0); this.visibleRows = new List<TreeGridRow>(); this.rowCache = new Dictionary<TreeGridNodeReference, TreeGridRow>(); this.selectedNodeReferences = new Dictionary<TreeGridNodeReference, TreeGridNodeReference>(); this.PreviewMouseDown += OnPreviewMouseDown; this.MouseWheel += OnMouseWheel; this.KeyDown += OnKeyDown; this.Focusable = true; this.selectionAnchorIndex = -1; this.rootNode = TreeGridNode.CreateRootNode(this); this.AddHandler(TreeGridRow.CurrentItemChangedEvent, (RoutedEventHandler)OnCurrentItemChanged); this.AddHandler(TreeGridRow.RowClickedEvent, (EventHandler<RowClickedEventArgs>)OnRowClicked); this.CommandBindings.Add(new CommandBinding(ExpandCommand, OnExpandExecuted, OnExpandCanExecute)); this.CommandBindings.Add(new CommandBinding(ExpandFullyCommand, OnExpandFullyExecuted, OnExpandFullyCanExecute)); this.CommandBindings.Add(new CommandBinding(ExpandAllCommand, OnExpandAllExecuted)); this.CommandBindings.Add(new CommandBinding(CollapseCommand, OnCollapseExecuted, OnCollapseCanExecute)); this.CommandBindings.Add(new CommandBinding(CollapseFullyCommand, OnCollapseFullyExecuted, OnCollapseFullyCanExecute)); this.CommandBindings.Add(new CommandBinding(CollapseAllCommand, OnCollapseAllExecuted)); this.CommandBindings.Add(new CommandBinding(SelectAllCommand, OnSelectAllExecuted)); this.AdditionalContextMenuItems = new ObservableCollection<MenuItem>(); this.AdditionalContextMenuItems.CollectionChanged += OnAdditionalContextMenuItemsCollectionChanged; }