private void HandleItemMoveRemoveReplaceHelper( ItemsGeneratorNode node, NotifyCollectionChangedEventArgs e, int nodeIndex ) { node.AdjustItemCount( e.NewItems.Count ); node.AdjustLeafCount( e.NewItems.Count ); this.IncrementCurrentGenerationCount(); //this is used to notify any Master Generator that it must update its content's status (UpdateGenPosToIndexList) this.SendAddEvent( new GeneratorPosition( -1, 1 ), nodeIndex + e.NewStartingIndex, e.NewItems.Count ); }
private void RemoveDetails( ItemsGeneratorNode node, int nodeStartIndex, int nodeEndIndex, int replaceCount ) { if( ( node.Details == null ) || ( node.Details.Count == 0 ) ) return; int removeCount = nodeEndIndex - nodeStartIndex + 1 - replaceCount; //Note: If a replace was invoked, replace count will be greater than 0, and will be used to properly re-offset the //details beyond the initial remove range. //Note2: for the case of a move or remove, the replace count must remain 0, so that the other details are correctly offseted. //first, create an array that will contain the keys for all the expanded details from the ItemsGeneratorNode int[] keys = new int[ node.Details.Count ]; node.Details.Keys.CopyTo( keys, 0 ); //sort the array, this will prevent any operation that will duplicate keys in the dictionary. Array.Sort<int>( keys ); //cycle through all of the old items int countDetailsRemoved = 0; foreach( int key in keys ) { //if the key is below the remove range, do not do anything with the dictionary entry //If the key match the remove range, remove the dictionary entry ( clear and queue remap ) if( ( key >= nodeStartIndex ) && ( key <= nodeEndIndex ) ) { List<DetailGeneratorNode> details; if( node.Details.TryGetValue( key, out details ) ) { //sum them foreach( DetailGeneratorNode detailNode in details ) { countDetailsRemoved += detailNode.ItemCount; } details.Clear(); //note: detail generators will be "closed" by another section of code (Remap floating details). #if LOG Log.WriteLine( this, "details.Remove - IN" + node.GetHashCode().ToString() + " - Di" + key.ToString() ); #endif node.Details.Remove( key ); if( node.Details.Count == 0 ) { node.Details = null; } } else { //Key not found in the dictionary, something wrong is going on. throw new DataGridInternalException(); } } //If the key is above the remove range, re-key it appropriatly. else if( key > nodeEndIndex ) { List<DetailGeneratorNode> details; if( node.Details.TryGetValue( key, out details ) ) { #if LOG Log.WriteLine( this, "details.offset for remove - IN" + node.GetHashCode().ToString() + "- Di" + key.ToString() + " - new Di" + ( key - removeCount ).ToString() ); #endif node.Details.Remove( key ); node.Details.Add( key - removeCount, details ); } else { //Key not found in the dictionary, something wrong is going on. throw new DataGridInternalException(); } } } //if some details have been "disconnected" if( countDetailsRemoved > 0 ) { node.AdjustItemCount( -countDetailsRemoved ); } }
private void HandleItemRemoveMoveReplace( ItemsGeneratorNode node, NotifyCollectionChangedEventArgs e ) { GeneratorNodeHelper nodeHelper = new GeneratorNodeHelper( node, 0, 0 ); //index not important for now. nodeHelper.ReverseCalculateIndex(); node.AdjustItemCount( -e.OldItems.Count ); node.AdjustLeafCount( -e.OldItems.Count ); int nodeStartIndex = e.OldStartingIndex; int nodeEndIndex = nodeStartIndex + e.OldItems.Count - 1; int detailCountToRemove = CustomItemContainerGenerator.ComputeDetailsCount( node, nodeStartIndex, nodeEndIndex ); int detailCountBeforeRemovedItems = 0; if( nodeStartIndex > 0 ) { detailCountBeforeRemovedItems = CustomItemContainerGenerator.ComputeDetailsCount( node, 0, nodeStartIndex - 1 ); } int startIndex = nodeHelper.Index + e.OldStartingIndex + detailCountBeforeRemovedItems; int endIndex = startIndex + detailCountToRemove + e.OldItems.Count - 1; int removeCount = e.OldItems.Count + detailCountToRemove; int replaceCount = ( e.Action == NotifyCollectionChangedAction.Replace ) ? e.NewItems.Count : 0; // *** RemoveDetails must be done before GeneratorPositionFromIndex, since GeneratorPositionFromIndex will indirectly do a RemapFloatingDetails // *** that will cause the index to already be rectified and make a double rectification to occurs. //Remove the details from the ItemsGeneratorNode and re-index the other details appropriatly. this.RemoveDetails( node, nodeStartIndex, nodeEndIndex, replaceCount ); GeneratorPosition removeGenPos = this.GeneratorPositionFromIndex( startIndex ); //Try to remap the old item for detail remapping (will do nothing if item has no details ) foreach( object oldItem in e.OldItems ) { this.QueueDetailItemForRemapping( oldItem ); } //if the node is totally expanded if( node.IsComputedExpanded ) { List<DependencyObject> removedContainers = new List<DependencyObject>(); int genRemCount = this.RemoveGeneratedItems( startIndex, endIndex, removedContainers ); this.IncrementCurrentGenerationCount(); this.SendRemoveEvent( removeGenPos, startIndex, removeCount, genRemCount, removedContainers ); } //then, based on the action that was performed (move, replace or remove) switch( e.Action ) { case NotifyCollectionChangedAction.Move: this.OffsetDetails( node, e.NewStartingIndex, e.NewItems.Count ); this.HandleItemMoveRemoveReplaceHelper( node, e, nodeHelper.Index ); break; case NotifyCollectionChangedAction.Replace: this.HandleItemMoveRemoveReplaceHelper( node, e, nodeHelper.Index ); break; case NotifyCollectionChangedAction.Remove: // Do nothing! break; case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Reset: default: throw new DataGridInternalException(); } }