internal void OnNodeInvalidated(TreeGridNodeReference invalidatedNodeRef) { bool updateNeeded = false; if (invalidatedNodeRef.Equals(this.currentNode)) { SetCurrentNode(null); updateNeeded = true; } if (this.selectedNodeReferences.ContainsKey(invalidatedNodeRef)) { RemoveNodeFromSelection(invalidatedNodeRef); updateNeeded = true; } if (!updateNeeded) { updateNeeded = this.visibleRows.Any(r => r.NodeReference.Equals(invalidatedNodeRef)); } if (updateNeeded) { InvalidateRowLayout(false); } }
TreeGridRow GetRowForNode(TreeGridNodeReference nodeRef) { TreeGridRow row; if (this.rowCache.TryGetValue(nodeRef, out row)) { // Found in the cache. That means the row is already in the canvas, and already has // the correct data. It may need its IsCurrent/IsSelected flags set, but other than // that we just need to position it vertically. Debug.Assert(row.NodeReference.Equals(nodeRef)); row.IsCurrent = (nodeRef.Equals(this.currentNode)); row.IsSelected = this.selectedNodeReferences.ContainsKey(nodeRef); row.UpdateExpansionState(); MoveRowToTopOfUsedList(row); if (this.fullRowLayoutRequired) { row.Width = double.NaN; row.Measure(infiniteSize); CollectDesiredColumnWidths(row); } else { row.Width = this.headerRow.DesiredSize.Width; } } else if ((this.rowCache.Count >= ((this.canvas.ActualHeight / this.headerRow.ActualHeight) * CachedPageCount)) && (this.tailOfRowCache != null) && (this.tailOfRowCache.lastLayoutPassUsed != this.rowLayoutPass)) { // Not in the cache with that row data, but the cache is full and thus has rows available for recycling. Use the oldest one. // it will be in the cache, but keyed under a different node. We need to remove it using that key (row.NodeReference) // and then update the row and add it to the cache with the new node reference key. row = this.tailOfRowCache; this.rowCache.Remove(row.NodeReference); row.UpdateRowData(nodeRef, nodeRef.Equals(this.currentNode), this.selectedNodeReferences.ContainsKey(nodeRef)); if (this.fullRowLayoutRequired) { row.Width = double.NaN; row.Measure(infiniteSize); CollectDesiredColumnWidths(row); } else { row.Width = this.headerRow.DesiredSize.Width; row.Measure(infiniteSize); } this.rowCache.Add(row.NodeReference, row); MoveRowToTopOfUsedList(row); } else { // Not in the cache, and we haven't created a full cache of rows yet. Create a new one now. row = new TreeGridRow(this, false); this.canvas.Children.Add(row); row.UpdateRowData(nodeRef, nodeRef.Equals(this.currentNode), this.selectedNodeReferences.ContainsKey(nodeRef)); if (this.fullRowLayoutRequired) { row.Width = double.NaN; row.UpdateLayout(); CollectDesiredColumnWidths(row); } else { row.Width = this.headerRow.DesiredSize.Width; row.UpdateLayout(); } // NOTE: Very important that we use the row's NodeReference value as the key here, because we need to make sure the // lifetime of the key outlives the lifetime of the row. (If we used nodeRef, for example, it gets mutated as we // progress through the paint, and then gets disposed at the end.) this.rowCache.Add(row.NodeReference, row); AddRowToUsedList(row); } return row; }