protected override Size ArrangeOverride(Size finalSize) { UpdateViewRange(); CellRangeDictionary showCells = new CellRangeDictionary(); foreach (int r in Rows.EnumerateVisibleElements(_viewRange.TopRow, _viewRange.BottomRow)) { var left = _viewRange.LeftColumn; // enumerate visible columns foreach (int c in Columns.EnumerateVisibleElements(left, _viewRange.RightColumn)) { var rng = new CellRange(r, c); showCells[rng] = null; } } // remove cells that are shown but shouldn't be List <CellRange> removeCells = new List <CellRange>(); foreach (var rng in _cells.Keys) { if (!showCells.ContainsKey(rng)) { removeCells.Add(rng); } } // create cells that should be shown but aren't foreach (var rng in showCells.Keys) { CreateCell(rng, removeCells); } for (int i = 0; i < removeCells.Count; i++) { RemoveCell(removeCells[i]); } foreach (KeyValuePair <CellRange, FrameworkElement> kvp in _cells) { // avoid re-creating the range based on element (for performance) var rng = kvp.Key; var cell = kvp.Value; if (rng.Row < 0 || rng.Row >= Rows.Count || rng.Column < 0 || rng.Column >= Columns.Count) { cell.Visibility = Visibility.Collapsed; } else { // get rectangle to arrange cell var rc = GetCellRect(rng); //if we has footerHeight //for example, footerHeight is 30, and row height is 30. //at the begining, show rows are 38-61, //after we has footerHeight, we should get 39-61 //and rect is not right at this time, we should rc.Y -= footerHeight; if (!Rows.IsFrozen(rng.Row)) { rc.Y -= footerHeight; } //fix auto column,if Width is Auto and AdaptUISize is true, the width will the adapt to UI width. if (Columns[rng.Column].AdaptUISize) { cell.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); if (cell.DesiredSize.Width > rc.Width) { rc.Width = cell.DesiredSize.Width + 5; Columns[rng.Column].SetSize(rc.Width); Columns.SetIsDirty(true); //if Cell has dirty data, we should also update Column if (CellType == CellType.Cell) { Grid.ColumnHeaders.Invalidate(); } //Column always render before cell, so we don't need invalidate cell right now. ////if column has dirty data, we should also update cell //else //{ // Grid.Cells.Invalidate(); //} } } // set clipping to account for frozen rows/columns if (Rows.Frozen > 0 || Columns.Frozen > 0) { cell.Clip = null; if (!Columns.IsFrozen(rng.Column) || !Rows.IsFrozen(rng.Row)) { // no clipping yet var rcClip = new Rect(0, 0, rc.Width, rc.Height); // clip unfrozen columns if (!Columns.IsFrozen(rng.Column)) { var fx = Columns.GetFrozenSize(); if (fx > 0 && rc.X < fx) { rcClip.X = fx - rc.X; } } // clip unfrozen rows if (!Rows.IsFrozen(rng.Row)) { var fy = Rows.GetFrozenSize(); if (fy > 0 && rc.Y < fy) { rcClip.Y = fy - rc.Y; } } // activate clip if (rcClip.X > 0 || rcClip.Y > 0) { cell.Clip = new RectangleGeometry() { Rect = rcClip }; } } } // limit editor size to grid cell (so trimming will work) cell.Width = rc.Width; cell.Height = rc.Height; // to finish the layout cell.Measure(new Size(rc.Width, rc.Height)); cell.Arrange(rc); } } if (currentPressedRow > -1) { HandlePointerPressed(currentPressedRow); } else { HandlePointerOver(currentpointerOverRow); } // measure content return(new Size(_cols.GetTotalSize(), _rows.GetTotalSize())); }