private void AdjustCellTabIndex( TableViewColumnVirtualizationManagerBase columnVirtualizationManager )
    {
      // The order of the children in the panel is not guaranteed to be good.  We do not reorder children because we will have to remove
      // and add them at a different location.  Doing that will cause more calculations to occur, so we only change the TabIndex.
      VirtualizingCellCollection collection = this.ParentRowCells;
      if( collection == null )
        return;

      var fieldNameToPositionMapping = columnVirtualizationManager.GetFieldNameToPosition( m_parentRow.LevelCache );
      var fieldNames = columnVirtualizationManager.GetFixedFieldNames( m_parentRow.LevelCache )
                         .Concat( columnVirtualizationManager.GetScrollingFieldNames( m_parentRow.LevelCache ) )
                         .Concat( m_permanentScrollingFieldNames );

      foreach( var fieldName in fieldNames )
      {
        Cell cell = collection.GetCell( fieldName, false );
        Debug.Assert( cell != null );

        int tabIndex;
        if( fieldNameToPositionMapping.TryGetValue( fieldName, out tabIndex ) )
        {
          KeyboardNavigation.SetTabIndex( cell, tabIndex );
        }
        else
        {
          cell.ClearValue( Cell.TabIndexProperty );
        }
      }
    }
      internal void UpdateReorderingInfo( TableViewColumnVirtualizationManagerBase columnVirtualizationManager )
      {
        // Do not create another instance since we want to keep the NewFixedColumnCount
        RequiredAnimationsInfo animationState = this.RequiredAnimations;
        animationState.AnimateToLeft.Clear();
        animationState.AnimateToRight.Clear();
        animationState.RollbackAnimation.Clear();

        List<ColumnBase> columnsByVisiblePosition = this.InitialColumnsByVisiblePosition;
        List<ColumnBase> reorderedColumnsByVisiblePosition = this.ReorderedColumnsByVisiblePosition;

        Debug.Assert( this.InitialColumnVisiblePosition < this.InitialColumnsByVisiblePosition.Count );

        ColumnBase draggedColumn = this.InitialColumnsByVisiblePosition[ this.InitialColumnVisiblePosition ];
        bool draggedColumnReached = false;
        int visibleColumnCount = columnsByVisiblePosition.Count;

        var columnsInView = columnVirtualizationManager.GetVisibleFieldNames( m_level );

        for( int i = 0; i < visibleColumnCount; i++ )
        {
          ColumnBase originalColumn = columnsByVisiblePosition[ i ];

          ColumnBase reorderedColumn = reorderedColumnsByVisiblePosition[ i ];

          if( reorderedColumn == draggedColumn )
          {
            draggedColumnReached = true;
            continue;
          }

          if( !reorderedColumn.Visible )
            continue;

          if( originalColumn == reorderedColumn )
          {
            this.ProcessAnimatedCollectionAddition( reorderedColumn, animationState.RollbackAnimation );
            continue;
          }

          if( columnsInView.Contains( reorderedColumn.FieldName ) )
          {
            if( !draggedColumnReached )
            {
              this.ProcessAnimatedCollectionAddition( reorderedColumn, animationState.AnimateToLeft );
            }
            else
            {
              this.ProcessAnimatedCollectionAddition( reorderedColumn, animationState.AnimateToRight );
            }
          }
        }

        animationState.DraggedColumnNewVisiblePosition = reorderedColumnsByVisiblePosition.IndexOf( draggedColumn );
      }
    private void UpdateChildren( DataGridContext dataGridContext, TableViewColumnVirtualizationManagerBase columnVirtualizationManager, VirtualizingCellCollection parentRowCells )
    {
      //Prevent reentrance
      if( ( parentRowCells == null ) || m_parentRowCells.IsUpdating )
        return;

      using( m_parentRowCells.SetIsUpdating() )
      {
        this.ClearPermanentScrollingFieldNames();

        //Retrieve the cells that aren't needed anymore.
        var unusedCells = ( from cell in parentRowCells.BindedCells
                            where !columnVirtualizationManager.GetScrollingFieldNames( m_parentRow.LevelCache ).Contains( cell.FieldName )
                               && !columnVirtualizationManager.GetFixedFieldNames( m_parentRow.LevelCache ).Contains( cell.FieldName )
                            select cell ).ToList();

        //Release the unused binded cells now in order to minimize the number of cell's creation.
        foreach( Cell cell in unusedCells )
        {
          this.AddCellToVisualTree( cell );

          if( this.CanReleaseCell( cell ) )
          {
            // Ensure to close the ContextMenu if it is open and the Cell is virtualized to avoid problems with ContextMenus defined as static resources
            // that won't be able to reopen again if the Close private method is called after the PlacementTarget is removed from the VisualTree
            var contextMenu = cell.ContextMenu;
            if( ( contextMenu != null ) && ( contextMenu.IsOpen ) )
            {
              contextMenu.IsOpen = false;
            }

            cell.ClearContainer();
            parentRowCells.Release( cell );
          }
          //Since the cell cannot be released, it will not be collapsed. We must keep the field
          //name in order to let the scrolling sub-panel measure and arrange the cell out of view.
          else
          {
            //Certain non recyclable cells like StatCells needs their content binding to be removed when they become out of view.
            cell.RemoveContentBinding();
            this.AddPermanentScrollingFieldNames( cell.FieldName );
          }
        }

        //Add the missing cells to the fixed region.
        foreach( string fieldName in columnVirtualizationManager.GetFixedFieldNames( m_parentRow.LevelCache ) )
        {
          //The cell is created if it is missing.
          Cell cell = parentRowCells[ fieldName ];

          //Certain non recyclable cells like StatCells need their content binding to be updated when they become (or stay) in view.
          cell.AddContentBinding( dataGridContext, this.ParentRow, this.Columns[ cell.FieldName ] );

          //Make sure the cell is in the appropriate panel.
          this.MoveCellToFixedPanel( cell );
        }

        //Add the missing cells to the scrolling region.
        foreach( string fieldName in columnVirtualizationManager.GetScrollingFieldNames( m_parentRow.LevelCache ) )
        {
          //The cell is created if it is missing.
          Cell cell = parentRowCells[ fieldName ];

          //Certain non recyclable cells like StatCells need their content binding to be updated when they become (or stay) in view.
          cell.AddContentBinding( dataGridContext, this.ParentRow, this.Columns[ cell.FieldName ] );

          //Make sure the cell is in the appropriate panel.
          this.MoveCellToScrollingPanel( cell );
        }

        if( m_clearUnusedCellsDispatcherOperation == null )
        {
          m_clearUnusedCellsDispatcherOperation = this.Dispatcher.BeginInvoke( new Action( this.ClearUnusedCells ), DispatcherPriority.ApplicationIdle );
        }

        m_fixedPanel.InvalidateMeasure();
        m_scrollingCellsDecorator.InvalidateMeasure();
        m_scrollingPanel.InvalidateMeasure();
      }
    }