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 ); } } }
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(); } }