internal Rect GetCellRect(int row, int col, bool clipToView, bool honorGroups) { // no negative indices if (col < 0) { col = 0; } if (row < 0) { row = 0; } if (row >= Rows.Count || col >= Columns.Count) { return(Rect.Empty); } // adjust for frozen cells var offsetX = Columns.IsFrozen(col) ? 0 : _scrollPos.X; var offsetY = Rows.IsFrozen(row) ? 0 : _scrollPos.Y; // build rectangle var rc = new Rect( _cols.GetItemPosition(col) + offsetX, _rows.GetItemPosition(row) + offsetY, _cols.GetItemSize(col), _rows.GetItemSize(row)); // honor frozen areas if (clipToView) { if (!Rows.IsFrozen(row)) { var fy = Rows.GetFrozenSize(); if (rc.Y < fy) { var b = rc.Bottom; rc.Y = fy; rc.Height = Math.Max(0, b - rc.Y); } } if (!Columns.IsFrozen(col)) { var fx = Columns.GetFrozenSize(); if (rc.X < fx) { var r = rc.Right; rc.X = fx; rc.Width = Math.Max(0, r - rc.X); } } } // done return(rc); }
internal CellRange GetViewRange(Point scrollPosition) { // get size, position, range var sz = DesiredSize; // account for frozen rows/columns var fx = Columns.GetFrozenSize(); var fy = Rows.GetFrozenSize(); var r = new CellRange(Rows.Frozen, Columns.Frozen); //var sv = _grid.OuterScrollViewer; //if (sv != null && (_grid.OuterScrollViewerVerticalScrollEnable || _grid.OuterScrollViewerHorizontalScrollEnable)) //{ // if (_grid.OuterScrollViewerVerticalScrollEnable) // { // sz.Height = sv.ActualHeight * 1.5; // var y = _grid.HeaderActualHeight - sv.VerticalOffset; // y += _grid.topToOuterScrollViewer; // r.Row = Rows.GetItemAt(-y - sv.ActualHeight); // r.Row2 = Math.Min(Rows.GetItemAt(sz.Height - y), Rows.Count - 1); // } // else // { // if (fy < sz.Height) // { // sz.Height = sv.ActualHeight; // r.Row = Rows.GetItemAt(fy - scrollPosition.Y); // r.Row2 = Math.Min(Rows.GetItemAt(sz.Height - scrollPosition.Y), Rows.Count - 1); // } // } // if (_grid.OuterScrollViewerHorizontalScrollEnable) // { // // find left/right columns // sz.Width = sv.ActualWidth * 1.5; // var x = -sv.HorizontalOffset; // r.Column = Columns.GetItemAt(-x - sv.ActualWidth); // r.Column2 = Math.Min(Columns.GetItemAt(sz.Width - x), Columns.Count - 1); // } // else // { // if (fx < sz.Width) // { // sz.Width = sv.ActualWidth; // r.Column = Columns.GetItemAt(fx - scrollPosition.X); // r.Column2 = Math.Min(Columns.GetItemAt(sz.Width - scrollPosition.X), Columns.Count - 1); // } // } //} //else { // find top/bottom rows if (fy < sz.Height) { r.Row = Rows.GetItemAt(fy - scrollPosition.Y); r.Row2 = Math.Min(Rows.GetItemAt(sz.Height - scrollPosition.Y), Rows.Count - 1); } // find left/right columns if (fx < sz.Width) { r.Column = Columns.GetItemAt(fx - scrollPosition.X); r.Column2 = Math.Min(Columns.GetItemAt(sz.Width - scrollPosition.X), Columns.Count - 1); } } if (r.Row < 0) { r.Row = 0; } if (r.Row2 < 0) { r.Row2 = 0; } if (r.Column < 0) { r.Column = 0; } if (r.Column2 < 0) { r.Column2 = 0; } // done return(r); }
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); //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); } } // measure content return(new Size(_cols.GetTotalSize(), _rows.GetTotalSize())); }