Пример #1
0
    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 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 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();
    }