internal void Invalidate(CellRange rng) { // negative parameters mean 'whole row' or 'whole column' if (rng.Row > -1 || rng.Column > -1)// Keep the range as invalid when rng.IsEmpty so that it can remove all the cells after a row was removed, otherwise it can leave non used cells because Rows.Count is less than there was in previous layout. { if (rng.Row < 0) { rng.Row = 0; rng.Row2 = Rows.Count - 1; } if (rng.Column < 0) { rng.Column = 0; rng.Column2 = Columns.Count - 1; } } // optimization (especially important when setting unbound values) if (rng.IsValid && !ViewRange.Intersects(rng) && !Columns.IsFrozen(rng.LeftColumn) && !Rows.IsFrozen(rng.TopRow)) { return; } // remove cells so they can be re-created List <CellRange> removeCells = new List <CellRange>(); foreach (var rg in _cells.Keys) { if (!rg.IsValid || !rng.IsValid || rg.Intersects(rng)) { removeCells.Add(rg); } } for (int i = 0; i < removeCells.Count; i++) { RemoveCell(removeCells[i]); } if (removeCells.Count == 0) { InvalidateArrange(); UpdateViewRange(); } }