private void InsertRange(FlatNode parentNode, IEnumerable items, int itemIndex) { foreach (var item in items) { Insert(parentNode, item, itemIndex++); } }
/// <summary> /// Gets the index of the node (where it must be inserted or removed). /// </summary> /// <param name="parentNode">The parent node.</param> /// <param name="itemIndex">Index of the item.</param> /// <returns></returns> private static int GetNodeIndex(FlatNode parentNode, int itemIndex) { // node index is parent node + 1 (parent node itself) + previous siblings size var nodeIndex = parentNode.Index + 1 + parentNode.GetChildOffset(itemIndex); return(nodeIndex); }
/// <summary> /// Inserts the visual child. /// And invalidates all impacted measures /// </summary> /// <param name="node">The node.</param> /// <param name="index">The index.</param> public void InsertVisualChild(FlatNode node, int index) { VisualChildren.Insert(index, node); for (int i = index + 1; i < VisualChildren.Count; i++) { VisualChildren[i]._childOffset++; } AdjustAncestorsSize(+1); }
private void CollapseNode(FlatNode itemNode) { if (!itemNode.IsExpanded) { return; } itemNode.IsExpanded = false; Delete(itemNode); }
private void ExpandNode(FlatNode itemNode) { if (itemNode.IsExpanded) { return; } itemNode.IsExpanded = true; var itemChildren = itemNode.Parent == null ? _hierarchicalSource.Source : _hierarchicalSource.GetChildren(itemNode.Item); SetChildrenSource(itemNode, itemChildren); if (itemChildren != null) { InsertRange(itemNode, itemChildren, 0); } }
private void SetChildrenSource(FlatNode itemNode, IEnumerable itemChildren) { if (ReferenceEquals(itemNode.ChildrenSource, itemChildren)) { return; } if (itemNode.ChildrenSource != null) { _nodesByChildren.Remove(itemNode.ChildrenSource); } itemNode.ChildrenSource.IfType <INotifyCollectionChanged>(c => c.CollectionChanged -= OnSourceCollectionChanged); itemNode.ChildrenSource = itemChildren; itemNode.ChildrenSource.IfType <INotifyCollectionChanged>(c => c.CollectionChanged += OnSourceCollectionChanged); if (itemNode.ChildrenSource != null) { _nodesByChildren[itemNode.ChildrenSource] = itemNode; } }
/// <summary> /// Initializes a new instance of the <see cref="FlatCollection" /> class. /// </summary> /// <param name="hierarchicalSource">The hierarchical source.</param> /// <param name="target">The target.</param> /// <exception cref="ArgumentNullException"> /// </exception> /// <exception cref="ArgumentException">Must be empty</exception> /// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentException">Must be empty</exception> public FlatCollection(IHierarchicalSource hierarchicalSource, IList target) { if (hierarchicalSource == null) { throw new ArgumentNullException(nameof(hierarchicalSource)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } if (target.Count > 0) { throw new ArgumentException(@"Must be empty", nameof(target)); } _hierarchicalSource = hierarchicalSource; _target = target; _rootNode = new FlatNode(null, null, true); SetChildrenSource(_rootNode, _hierarchicalSource.Source); InsertRange(_rootNode, _rootNode.ChildrenSource, 0); }
private void Insert(FlatNode parentNode, object item, int itemIndex) { var insertIndex = GetNodeIndex(parentNode, itemIndex); _target.Insert(insertIndex, _hierarchicalSource.GetContainerForItem(item)); var itemNode = new FlatNode(item, parentNode, _hierarchicalSource.IsExpanded(item)); parentNode.InsertVisualChild(itemNode, itemIndex); _nodes[item] = itemNode; if (itemNode.IsExpanded) { var itemChildren = _hierarchicalSource.GetChildren(item); if (itemChildren != null) { SetChildrenSource(itemNode, itemChildren); InsertRange(itemNode, itemChildren, 0); } } }
private void OnSourceCollectionChanged(FlatNode itemNode, NotifyCollectionChangedEventArgs e) { // at any level, a parent may be collapsed, so we won't update anything at all here for (var ancestor = itemNode; ancestor != null; ancestor = ancestor.Parent) { if (!ancestor.IsExpanded) { return; } } switch (e.Action) { case NotifyCollectionChangedAction.Add: InsertRange(itemNode, e.NewItems, e.NewStartingIndex); break; case NotifyCollectionChangedAction.Remove: DeleteRange(e.OldItems); break; case NotifyCollectionChangedAction.Replace: DeleteRange(e.OldItems); InsertRange(itemNode, e.NewItems, e.NewStartingIndex); break; case NotifyCollectionChangedAction.Move: // :confounded: throw new NotImplementedException(); case NotifyCollectionChangedAction.Reset: CollapseNode(itemNode); ExpandNode(itemNode); break; default: throw new ArgumentOutOfRangeException(); } }
private void Delete(FlatNode node) { Delete(node.VisualChildren.ToArray()); SetChildrenSource(node, null); }
/// <summary> /// Initializes a new instance of the <see cref="FlatNode" /> class. /// </summary> /// <param name="item">The item.</param> /// <param name="parent">The parent.</param> /// <param name="isExpanded">if set to <c>true</c> [is expanded].</param> public FlatNode(object item, FlatNode parent, bool isExpanded) { Item = item; Parent = parent; IsExpanded = isExpanded; }