/// <summary> /// Updates the tree if items were removed from an observed /// child collection. This might cause rendered tree nodes /// to be removed. In case lazy loading is enabled, the update /// of the UI may be as subtle as to remove an expander from /// a collapsed node if the represented item's childs were /// removed. /// </summary> /// <param name="observed">The observed collection.</param> /// <param name="e">The event arguments that provide the /// removed items.</param> private void HandleRemovedChildItems(ICollection <T> observed, NotifyCollectionChangedEventArgs e) { IList childs = e.OldItems; if (childs.Count == 0) { return; } //get the node of the parent item that contains the evented childs TreeViewItem parentNode = GetParentNode((T)childs[0], observed); if (parentNode == null) { return; } foreach (T childItem in childs) { string itemKey = tree.GetItemKey(childItem); //check if we have a corresponding open node //-> not necessarily the case if we're doing lazy loading TreeViewItem childNode; childNode = tree.TryFindItemNode(parentNode.Items, itemKey, false); if (childNode != null) { //unregister listeners UnregisterListeners(childNode); //remove node from UI parentNode.Items.Remove(childNode); } } //in case of lazy loading, the tree might contain a dummy node //(has not been expanded). However, it might be that it's now //completely empty... if (observed.Count == 0) { TreeUtil.ClearDummyChildNode(parentNode); parentNode.IsExpanded = false; } }
/// <summary> /// Handles lazy creation of child nodes if a node is being expanded /// the first time. /// </summary> protected virtual void OnNodeExpanded(TreeViewItem treeNode) { //the node does not represent one of our bound items //(custom root or some injected stuff) T item = treeNode.Header as T; if (item == null) { return; } //update the layout string itemKey = GetItemKey(item); currentLayout.ExpandedNodeIds.Add(itemKey); //the tree has already been created - there is nothing more to do here if (!IsLazyLoading) { //the tree has already been created - there is nothing more to do here //however, if the node does not contain anything, don't show as expanded if (treeNode.Items.Count == 0) { treeNode.IsExpanded = false; currentLayout.ExpandedNodeIds.Remove(itemKey); } return; } //if we have a dummy node, remove it TreeUtil.ClearDummyChildNode(treeNode); //get the child items ICollection <T> childItems = GetChildItems(item); if (treeNode.Items.Count == 0) { foreach (T childItem in childItems) { //create child items with the current layout //-> this also re-expands subitems that were //expanded, but discarded with their ancestor CreateItemNode(childItem, treeNode.Items, currentLayout); } //refresh to apply sorting if (treeNode.Items.NeedsRefresh) { treeNode.Items.Refresh(); } } if (treeNode.Items.Count == 0) { //collapse again if there was no data at all //unlikely, but the bound item's childs might have changed treeNode.IsExpanded = false; currentLayout.ExpandedNodeIds.Remove(itemKey); } }