private void RecycleContainer( ICustomItemContainerGenerator generator, int containerIndex, UIElement container ) { if( ( generator != null ) && ( containerIndex != -1 ) ) { try { GeneratorPosition position = generator.GeneratorPositionFromIndex( containerIndex ); generator.Remove( position, 1 ); } catch { Debug.Fail( "Unable to remove container for containerIndex " + containerIndex ); } } #if DEBUG TableflowViewItemsHost.SetRealizedIndex( container, -1 ); #endif //DEBUG TableflowViewItemsHost.ClearIsSticky( container ); container.ClearValue( UIElement.ClipProperty ); this.DisableElementNavigation( container ); this.FreeRowSelector( container ); m_layoutedContainersToRecycle.Add( container ); }
private void GenerateContainers( ICustomItemContainerGenerator generator, int pageStartIndex, int pageEndIndex, bool measureInvalidated, ref UIElement focusedElement ) { HashSet<UIElement> unusedLayoutedContainers = new HashSet<UIElement>( m_layoutedContainers.Select( item => item.Container ) ); m_layoutedContainers.Clear(); ScrollDirection scrollDirection = this.AnimatedScrollInfo.VerticalScrollingDirection; GeneratorPosition position; GeneratorDirection direction; int currentIndex; int step; if( ( scrollDirection == ScrollDirection.Forward ) || ( scrollDirection == ScrollDirection.None ) ) { position = generator.GeneratorPositionFromIndex( pageStartIndex ); direction = GeneratorDirection.Forward; currentIndex = pageStartIndex; step = 1; } else { position = generator.GeneratorPositionFromIndex( pageEndIndex ); direction = GeneratorDirection.Backward; currentIndex = pageEndIndex; step = -1; } using( generator.StartAt( position, direction, true ) ) { while( ( currentIndex >= pageStartIndex ) && ( currentIndex <= pageEndIndex ) ) { UIElement container = this.GenerateContainer( generator, currentIndex, measureInvalidated, true ); if( container == null ) break; if( focusedElement == container ) { focusedElement = null; } // The container is now part of the page layout. Add it to the list. m_layoutedContainers.Add( new LayoutedContainerInfo( currentIndex, container ) ); m_layoutedContainersToRecycle.Remove( container ); unusedLayoutedContainers.Remove( container ); currentIndex += step; } } // A ScrollViewer may measure forever if the containers that are "underneath" the horizontal // scrollbar are the ones that required the scrollbar in the first place. if( m_lastVisiblePageIndexes != PageIndexes.Empty ) { int remainingItemCount = ( m_lastVisiblePageIndexes.EndIndex - m_lastVisiblePageIndexes.StartIndex ) - ( pageEndIndex - pageStartIndex ); if( ( remainingItemCount > 0 ) && ( this.GetMaxDesiredWidth() < this.AnimatedScrollInfo.ExtentWidth ) ) { int itemCount = generator.ItemCount; if( ( currentIndex >= 0 ) && ( currentIndex < itemCount ) ) { position = generator.GeneratorPositionFromIndex( currentIndex ); using( generator.StartAt( position, direction, true ) ) { while( ( remainingItemCount > 0 ) && ( currentIndex >= 0 ) && ( currentIndex < itemCount ) ) { UIElement container = this.GenerateContainer( generator, currentIndex, measureInvalidated, true ); if( container == null ) break; if( focusedElement == container ) { focusedElement = null; } // The container is now part of the page layout. Add it to the list. m_layoutedContainers.Add( new LayoutedContainerInfo( currentIndex, container ) ); m_layoutedContainersToRecycle.Remove( container ); unusedLayoutedContainers.Remove( container ); currentIndex += step; remainingItemCount--; } } } } } m_layoutedContainers.Sort(); // Recycle the containers that have not been reused in the current page. foreach( var container in unusedLayoutedContainers ) { // We do not recycle the focused element! if( container.IsKeyboardFocusWithin ) { Debug.Assert( focusedElement == null ); focusedElement = container; } else { int index = generator.GetRealizedIndexForContainer( container ); this.RecycleContainer( generator, index, container ); m_layoutedContainersToRecycle.Add( container ); } } }
private void RecycleContainer( ICustomItemContainerGenerator generator, LayoutedContainerInfo containerInfo ) { Debug.Assert( containerInfo != null ); var index = containerInfo.RealizedIndex; if( ( generator != null ) && ( index >= 0 ) ) { try { var position = generator.GeneratorPositionFromIndex( index ); generator.Remove( position, 1 ); } catch { Debug.Fail( "Unable to remove container for containerIndex " + index ); } } this.ClearContainer( containerInfo.Container ); }
private void GenerateContainers( ICustomItemContainerGenerator generator, double pageHeight, HashSet<UIElement> layoutedContainersToRecycle, bool measureInvalidated, ref PageIndexes pageIndexes, out double containersHeight ) { int currentIndex = pageIndexes.StartIndex; GeneratorDirection direction; if( currentIndex == -1 ) { currentIndex = pageIndexes.EndIndex; Debug.Assert( currentIndex != -1 ); direction = GeneratorDirection.Backward; } else { direction = GeneratorDirection.Forward; } int startIndex = currentIndex; int endIndex = currentIndex; containersHeight = 0d; GeneratorPosition position; position = generator.GeneratorPositionFromIndex( currentIndex ); int itemCount = generator.ItemCount; using( generator.StartAt( position, direction, true ) ) { while( ( ( direction == GeneratorDirection.Forward ) ? ( currentIndex < itemCount ) : ( currentIndex >= 0 ) ) && ( pageHeight > 0 ) ) { UIElement container = this.GenerateContainer( generator, currentIndex, measureInvalidated ); if( container == null ) break; double containerHeight = container.DesiredSize.Height; m_layoutedContainers.Add( new LayoutedContainerInfo( currentIndex, container ) ); layoutedContainersToRecycle.Remove( container ); m_layoutedContainersToRecycle.Remove( container ); if( ( direction == GeneratorDirection.Backward ) && ( ( pageHeight - containerHeight ) < 0 ) ) { // We do not want to recycle the container since it will cause a re-invalidation of the measure and // may cause an infinit loop. This case has been observed with a MaxHeight set on the DataGridControl. break; } pageHeight -= containerHeight; containersHeight += containerHeight; endIndex = currentIndex; currentIndex += ( direction == GeneratorDirection.Forward ) ? 1 : -1; } } if( pageHeight > 0 ) { if( direction == GeneratorDirection.Forward ) { direction = GeneratorDirection.Backward; } else { direction = GeneratorDirection.Forward; } DataGridContext dataGridContext = DataGridControl.GetDataGridContext( this ); if( ( direction == GeneratorDirection.Forward ) || ( ( dataGridContext == null ) || ( TableView.GetAutoFillLastPage( dataGridContext ) ) ) ) { currentIndex = ( direction == GeneratorDirection.Forward ) ? startIndex + 1 : startIndex - 1; if( ( direction == GeneratorDirection.Forward ) ? ( currentIndex < itemCount ) : ( currentIndex >= 0 ) ) { position = generator.GeneratorPositionFromIndex( currentIndex ); using( generator.StartAt( position, direction, true ) ) { // If we still have more space, try to get more container to fill up the page. while( ( ( direction == GeneratorDirection.Forward ) ? ( currentIndex < itemCount ) : ( currentIndex >= 0 ) ) && ( pageHeight > 0 ) ) { UIElement container = this.GenerateContainer( generator, currentIndex, measureInvalidated ); if( container == null ) break; double containerHeight = container.DesiredSize.Height; pageHeight -= containerHeight; m_layoutedContainers.Add( new LayoutedContainerInfo( currentIndex, container ) ); layoutedContainersToRecycle.Remove( container ); m_layoutedContainersToRecycle.Remove( container ); if( ( direction == GeneratorDirection.Backward ) && ( pageHeight < 0 ) ) { // We do not want to recycle the container since it will cause a re-invalidation of the measure and // may cause an infinit loop. This case has been observed with a MaxHeight set on the DataGridControl. break; } containersHeight += containerHeight; startIndex = currentIndex; currentIndex += ( direction == GeneratorDirection.Forward ) ? 1 : -1; } } } } } m_layoutedContainers.Sort(); if( startIndex > endIndex ) { pageIndexes = new PageIndexes( endIndex, startIndex ); } else { pageIndexes = new PageIndexes( startIndex, endIndex ); } }
private void TrySafeRecycleContainer( ICustomItemContainerGenerator generator, int containerIndex, UIElement container ) { int newIndex = -1; if( ( generator != null ) && ( containerIndex != -1 ) ) { GeneratorPosition position = generator.GeneratorPositionFromIndex( containerIndex ); if( ( position.Index != -1 ) && ( position.Offset == 0 ) ) { newIndex = containerIndex; } } this.RecycleContainer( generator, newIndex, container ); }
private void RecycleContainer( ICustomItemContainerGenerator generator, int containerIndex, UIElement container ) { if( ( generator != null ) && ( containerIndex != -1 ) ) { try { GeneratorPosition position = generator.GeneratorPositionFromIndex( containerIndex ); generator.Remove( position, 1 ); } catch { Debug.Fail( "Unable to remove container for containerIndex " + containerIndex ); } } this.DisableElementNavigation( container ); this.FreeRowSelector( container ); }
private void GenerateContainers( ICustomItemContainerGenerator generator, int pageStartIndex, int pageEndIndex, bool measureInvalidated, ref UIElement focusedElement ) { ScrollDirection scrollDirection = this.AnimatedScrollInfo.VerticalScrollingDirection; GeneratorPosition position; GeneratorDirection direction; if( ( scrollDirection == ScrollDirection.Forward ) || ( scrollDirection == ScrollDirection.None ) ) { position = generator.GeneratorPositionFromIndex( pageStartIndex ); direction = GeneratorDirection.Forward; } else { position = generator.GeneratorPositionFromIndex( pageEndIndex ); direction = GeneratorDirection.Backward; } using( generator.StartAt( position, direction, true ) ) { int currentIndex = ( direction == GeneratorDirection.Forward ) ? pageStartIndex : pageEndIndex; while( ( direction == GeneratorDirection.Forward ) ? ( currentIndex <= pageEndIndex ) : ( currentIndex >= pageStartIndex ) ) { UIElement container = this.GenerateContainer( generator, currentIndex, measureInvalidated, true ); if( container == null ) return; if( ( focusedElement != null ) && ( focusedElement == container ) ) { focusedElement = null; } // The container is now part of the page layout. Add it to the list. m_layoutedContainers.Add( new LayoutedContainerInfo( currentIndex, container ) ); m_layoutedContainersToRecycle.Remove( container ); currentIndex += ( direction == GeneratorDirection.Forward ) ? 1 : -1; } } m_layoutedContainers.Sort(); }