예제 #1
0
        /// <summary>
        /// [email protected]: In UiGrid, we have conditions, were a merged cell chooses to increase the column span (say 2 to 9).
        /// In this condition, sourcegrid requires user to delete the exisiting cells.So that the merged cell can occupy this portion.
        /// </summary>
        private void DeleteCellsExistingInSpannedArea(int row, int col, Cells.ICell cell)
        {
            if (AllowOverlappingCells)
            {
                return;
            }

            for (int y = row; y < row + cell.RowSpan; y++)
            {
                for (int x = col; x < col + cell.ColumnSpan; x++)
                {
                    if (x == col && y == row)
                    {
                        continue;
                    }

                    Cells.ICell existingSpannedCell = DirectGetCell(new Position(y, x));

                    if (existingSpannedCell != null)
                    {
                        RemoveSpannedCell(new Position(y, x));
                        DirectSetCell(new Position(y, x), null);
                    }
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Check
 /// </summary>
 private void EnsureNoOtherCellsExist(int row, int col, Cells.ICell p_cell)
 {
     for (int y = row; y < row + p_cell.RowSpan; y++)
     {
         for (int x = col; x < col + p_cell.ColumnSpan; x++)
         {
             if (x == col && y == row)
             {
                 continue;
             }
             Cells.ICell existingSpannedCell = this.DirectGetCell(y, x);
             if (existingSpannedCell != null)
             {
                 if (existingSpannedCell != p_cell)
                 {
                     throw new OverlappingCellException(string.Format(
                                                            "Given cell at position ({0}, {1}), " +
                                                            "intersects with another cell " +
                                                            "at position ({2}, {3}) '{4}'",
                                                            row, col,
                                                            existingSpannedCell.Row.Index,
                                                            existingSpannedCell.Column.Index,
                                                            existingSpannedCell.DisplayText));
                 }
             }
         }
     }
 }
예제 #3
0
        private void EnsureNoSpannedCellsExist(int row, int col, Cells.ICell p_cell)
        {
            var spanRange = new Range(row, col, row + p_cell.RowSpan - 1, col + p_cell.ColumnSpan - 1);
            var ranges    = spannedCellReferences.SpannedRangesCollection.GetRanges(
                spanRange);

            if (ranges.Count == 0)
            {
                return;
            }

            var start = new Position(row, col);

            foreach (var range in ranges)
            {
                if (start.Equals(range.Start) == true)
                {
                    continue;
                }
                Cells.ICell existingSpannedCell = this[range.Start];
                if (existingSpannedCell == null)
                {
                    throw new ArgumentException("internal error. please report this bug to developers");
                }
                throw new OverlappingCellException(string.Format(
                                                       "Given cell at position ({0}, {1}), " +
                                                       "intersects with another cell " +
                                                       "at position ({2}, {3}) '{4}'",
                                                       row, col,
                                                       existingSpannedCell.Row.Index,
                                                       existingSpannedCell.Column.Index,
                                                       existingSpannedCell.DisplayText));
            }
        }
예제 #4
0
        private void EnsureDestinationSpannedAreaisCompletelyEmpty(int row, int col, int rowSpan, int colSpan)
        {
            if (AllowOverlappingCells)
            {
                return;
            }

            for (int y = row; y < row + rowSpan; y++)
            {
                for (int x = col; x < col + colSpan; x++)
                {
                    Cells.ICell existingSpannedCell = this[y, x];
                    if (existingSpannedCell != null)
                    {
                        throw new OverlappingCellException(string.Format(
                                                               "Given cell at position ({0}, {1}), " +
                                                               "intersects with another cell " +
                                                               "at position ({2}, {3}) '{4}'",
                                                               row, col,
                                                               (existingSpannedCell.Row != null)?existingSpannedCell.Row.Index : -1,
                                                               (existingSpannedCell.Column != null)?existingSpannedCell.Column.Index : -1,
                                                               existingSpannedCell.DisplayText));
                    }
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Force a redraw of the specified cell
 /// </summary>
 /// <param name="p_Cell"></param>
 public virtual void InvalidateCell(Cells.ICell p_Cell)
 {
     if (p_Cell != null)
     {
         base.InvalidateRange(p_Cell.Range);
     }
 }
예제 #6
0
        private void Selection_RemovingRange(object sender, RangeRegionCancelEventArgs e)
        {
            //se è abilitato RowColSpan devo assicurarmi di selezionare la cella di origine e non quella che sfrutta il RowCol Span
            if (EnableRowColSpan)
            {
                RangeCollection rangesToRemove = e.RangeRegion.GetRanges();
                for (int iRange = 0; iRange < rangesToRemove.Count; iRange++)
                {
                    Range rng = rangesToRemove[iRange];
                    for (int r = rng.Start.Row; r <= rng.End.Row; r++)
                    {
                        for (int c = rng.Start.Column; c <= rng.End.Column; c++)
                        {
                            Cells.ICell l_Cell = this[r, c];                           //N.B. questo metodo mi restituisce la cella reale (anche se questa posizione è occupata slo perchè in mee con Row/Col Span)
                            if (l_Cell != null)
                            {
                                Range l_Range = l_Cell.Range;

                                if (l_Range != new Range(new Position(r, c)))                       //se la cella occupa più righe o colonne
                                {
                                    e.RangeRegion.Add(l_Range);                                     //la seleziono tutta
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
        //[email protected] : Getting the correct row span. Previous implementation
        // was not considering the row sapn of current row header
        private static int GetRowSpan(Cells.ICell cell, int startIndex, int count)
        {
            const int defaultRowSpan = 1;

            if (cell == null)
            {
                return(defaultRowSpan);
            }

            int endIndex          = startIndex + count - 1;
            int startSpannedIndex = cell.Range.Start.Row;
            int endSpannedIndex   = cell.Range.End.Row;
            int rowSpan           = cell.RowSpan;

            if (startSpannedIndex >= startIndex)
            {
                return(rowSpan);
            }
            if (endSpannedIndex < endIndex)
            {
                return(startIndex - startSpannedIndex);
            }
            rowSpan = rowSpan - count;
            return(rowSpan);
        }
예제 #8
0
        private void DirectSetCell(Position position, Cells.ICell cell)
        {
            if (OptimizeMode == CellOptimizeMode.ForRows)
            {
                GridRow row = Rows[position.Row];
                if (position.Column >= Columns.Count)
                {
                    throw new ArgumentException(string.Format(
                                                    "Grid has only {0} columns, you tried to insert cell into position {1}." +
                                                    "You should probably call Redim on grid to increase it's column size",
                                                    Columns.Count, position.ToString()));
                }

                row[Columns[position.Column] as GridColumn] = cell;
            }
            else if (OptimizeMode == CellOptimizeMode.ForColumns)
            {
                GridColumn col = Columns[position.Column] as GridColumn;

                col[Rows[position.Row]] = cell;
            }
            else
            {
                throw new SourceGridException("Invalid OptimizeMode");
            }
        }
예제 #9
0
 /// <summary>
 /// Set the focus to the specified cell (the specified cell became the active cell, FocusCell property).
 /// </summary>
 /// <param name="p_CellToSetFocus"></param>
 /// <returns></returns>
 public bool SetFocusCell(Cells.ICell p_CellToSetFocus)
 {
     if (p_CellToSetFocus == null)
     {
         return(Selection.Focus(Position.Empty));
     }
     else
     {
         return(Selection.Focus(p_CellToSetFocus.Range.Start));
     }
 }
예제 #10
0
 /// <summary>
 /// Scroll the view to show the specified cell
 /// </summary>
 /// <param name="p_CellToShow"></param>
 /// <returns></returns>
 public bool ShowCell(Cells.ICell p_CellToShow)
 {
     if (p_CellToShow != null)
     {
         return(base.ShowCell(p_CellToShow.Range.Start));
     }
     else
     {
         return(true);
     }
 }
예제 #11
0
        /// <summary>
        /// Remove the specified cell
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        private void RemoveCell(int row, int col)
        {
            Cells.ICell tmp = DirectGetCell(new Position(row, col));

            if (tmp != null)
            {
                tmp.UnBindToGrid();

                DirectSetCell(new Position(row, col), null);
            }
        }
예제 #12
0
 /// <summary>
 /// Returns true if the specified cell is visible otherwise false
 /// </summary>
 /// <param name="p_Cell"></param>
 /// <returns></returns>
 public bool IsCellVisible(Cells.ICell p_Cell)
 {
     if (p_Cell != null)
     {
         return(base.IsCellVisible(p_Cell.Range.Start));
     }
     else
     {
         return(true);
     }
 }
예제 #13
0
 /// <summary>
 /// Force a cell to redraw. If Redraw is set to false this function has no effects. If ColSpan or RowSpan is greater than 0 this function invalidate the complete range with InvalidateRange
 /// </summary>
 /// <param name="p_Position"></param>
 public override void InvalidateCell(Position p_Position)
 {
     Cells.ICell l_Cell = this[p_Position.Row, p_Position.Column];
     if (l_Cell == null)
     {
         base.InvalidateCell(p_Position);
     }
     else
     {
         InvalidateRange(l_Cell.Range);
     }
 }
예제 #14
0
 /// <summary>
 /// Force a cell to redraw. If ColSpan or RowSpan is greater than 0 this function invalidate the complete range with InvalidateRange
 /// </summary>
 /// <param name="p_Position"></param>
 public override void InvalidateCell(Position p_Position)
 {
     Cells.ICell cell = this[p_Position.Row, p_Position.Column];
     if (cell == null || (cell.Range.ColumnsCount == 1 && cell.Range.RowsCount == 1))
     {
         base.InvalidateCell(p_Position);
     }
     else
     {
         InvalidateRange(cell.Range);
     }
 }
예제 #15
0
 public override Size PositionToSize(Position position)
 {
     Cells.ICell cell = this[position.Row, position.Column];
     if (cell != null)
     {
         return(base.RangeToRectangle(cell.Range).Size);
     }
     else
     {
         return(base.PositionToSize(position));
     }
 }
예제 #16
0
 /// <summary>
 /// Get the Rectangle of the cell respect all the scrollable area. Using the Cell Row/Col Span.
 /// </summary>
 /// <param name="position"></param>
 /// <returns></returns>
 public override Rectangle PositionToRectangleRelative(int?relativeRow, int?relativeCol, Position position)
 {
     Cells.ICell cell = this[position.Row, position.Column];
     if (cell != null)
     {
         return(RangeToRectangleRelative(relativeRow, relativeCol, cell.Range));
     }
     else
     {
         return(base.PositionToRectangleRelative(relativeRow, relativeCol, position));
     }
 }
예제 #17
0
        /// <summary>
        /// Remove the specified cell
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        private void RemoveCell(int row, int col)
        {
            Cells.ICell cell = DirectGetCell(new Position(row, col));

            if (cell == null)
            {
                return;
            }
            cell.UnBindToGrid();

            RemoveSpannedCell(new Position(row, col));
            DirectSetCell(new Position(row, col), null);
        }
예제 #18
0
        /// <summary>
        /// Insert the specified cell
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="p_cell"></param>
        private void InsertCell(int row, int col, Cells.ICell p_cell)
        {
            RemoveCell(row, col);

            if (p_cell != null && p_cell.Grid != null)
            {
                throw new ArgumentException("This cell already have a linked grid", "p_cell");
            }

            DirectSetCell(new Position(row, col), p_cell);

            if (p_cell != null)
            {
                p_cell.BindToGrid(this, new Position(row, col));
            }
        }
예제 #19
0
 public Cells.ICell this[Position position]
 {
     get
     {
         Cells.ICell cell = DirectGetCell(position);
         if (cell != null)
         {
             return(cell);
         }
         return(GetSpannedCell(position));
     }
     set
     {
         InsertCell(position.Row, position.Column, value);
     }
 }
예제 #20
0
        /// <summary>
        /// This method converts a Position to the real range of the cell. This is usefull when RowSpan or ColumnSpan is greater than 1.
        /// For example suppose to have at grid[0,0] a cell with ColumnSpan equal to 2. If you call this method with the position 0,0 returns 0,0-0,1 and if you call this method with 0,1 return again 0,0-0,1.
        /// </summary>
        /// <param name="pPosition"></param>
        /// <returns></returns>
        public override Range PositionToCellRange(Position pPosition)
        {
            if (pPosition.IsEmpty())
            {
                return(Range.Empty);
            }

            Cells.ICell l_Cell = this[pPosition.Row, pPosition.Column];
            if (l_Cell == null)
            {
                return(new Range(pPosition));
            }
            else
            {
                return(l_Cell.Range);
            }
        }
예제 #21
0
        private void m_Columns_ColumnsRemoved(object sender, IndexRangeEventArgs e)
        {
            //N.B. Uso m_Cells.GetLength(0) anziche' RowsCount e
            // m_Cells.GetLength(1) anziche' ColumnsCount per essere sicuro di lavorare sulle righe effetivamente allocate

            for (int c = (e.StartIndex + e.Count); c < CellsCols; c++)
            {
                for (int r = 0; r < CellsRows; r++)
                {
                    Cells.ICell tmp = m_Cells[r, c];
                    RemoveCell(r, c);
                    InsertCell(r, c - e.Count, tmp);
                }
            }

            RedimCellsMatrix(CellsRows, CellsCols - e.Count);
        }
예제 #22
0
        /// <summary>
        /// Insert the specified cell (for best performance set Redraw property to false)
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="p_cell"></param>
        public virtual void InsertCell(int row, int col, Cells.ICell p_cell)
        {
            RemoveCell(row, col);
            m_Cells[row, col] = p_cell;

            if (p_cell != null)
            {
                if (p_cell.Grid != null)
                {
                    throw new ArgumentException("This cell already have a linked grid", "p_cell");
                }

                p_cell.BindToGrid(this, new Position(row, col));

                p_cell.Invalidate();
            }
        }
예제 #23
0
        private void m_Columns_ColumnsAdded(object sender, IndexRangeEventArgs e)
        {
            //N.B. Uso m_Cells.GetLength(0) anziche' RowsCount e
            // m_Cells.GetLength(1) anziche' ColumnsCount per essere sicuro di lavorare sulle righe effetivamente allocate

            RedimCellsMatrix(CellsRows, CellsCols + e.Count);

            //dopo aver ridimensionato la matrice sposto le celle in modo da fare spazio alla nuove righe
            for (int c = CellsCols - 1; c > (e.StartIndex + e.Count - 1); c--)
            {
                for (int r = 0; r < CellsRows; r++)
                {
                    Cells.ICell tmp = m_Cells[r, c - e.Count];
                    RemoveCell(r, c - e.Count);
                    InsertCell(r, c, tmp);
                }
            }
        }
예제 #24
0
        ///// <summary>
        ///// Array of cells
        ///// </summary>
        //private Cells.ICell[,] m_Cells = null;
        //private int CellsRows
        //{
        //    get
        //    {
        //        if (m_Cells==null)
        //            return 0;
        //        else
        //            return m_Cells.GetLength(0);
        //    }
        //}
        //private int CellsCols
        //{
        //    get
        //    {
        //        if (m_Cells==null)
        //            return 0;
        //        else
        //            return m_Cells.GetLength(1);
        //    }
        //}

        private void DirectSetCell(Position position, Cells.ICell cell)
        {
            if (OptimizeMode == CellOptimizeMode.ForRows)
            {
                GridRow row = Rows[position.Row];

                row[Columns[position.Column]] = cell;
            }
            else if (OptimizeMode == CellOptimizeMode.ForColumns)
            {
                GridColumn col = Columns[position.Column];

                col[Rows[position.Row]] = cell;
            }
            else
            {
                throw new SourceGridException("Invalid OptimizeMode");
            }
        }
예제 #25
0
        /// <summary>
        /// Check if a cell exists in spanned cells.
        /// If yes, returns. If no, returns null
        /// </summary>
        private Cells.ICell GetSpannedCell(Position pos)
        {
            var range = spannedCellReferences.SpannedRangesCollection.GetFirstIntersectedRange(pos);

            if (range == null)
            {
                return(null);
            }
            Position cellPos = range.Value.Start;

            Cells.ICell cell = DirectGetCell(cellPos);
            if (cell == null)
            {
                throw new ArgumentException(string.Format(
                                                "Invalid grid state. Grid should contain a spanned cell at position {0}, " +
                                                " but apparently it does not!", cellPos));
            }
            return(cell);
        }
예제 #26
0
        /// <summary>
        /// Remove the specified cell
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        public virtual void RemoveCell(int row, int col)
        {
            Cells.ICell tmp = m_Cells[row, col];

            if (tmp != null)
            {
#if !MINI
                //se per caso la cella era quella correntemente con il mouse metta quest'ultima a null
                if (tmp == MouseCell)
                {
                    ChangeMouseCell(Position.Empty);
                }
#endif

                tmp.Select = false;               //deseleziono la cella (per evitare che venga rimossa senza essere stata aggiunta alla lista di selection
                tmp.LeaveFocus();                 //tolgo l'eventuale focus dalla cella

                tmp.UnBindToGrid();

                m_Cells[row, col] = null;
            }
        }
예제 #27
0
        /// <summary>
        /// Returns all the cells at specified column position
        /// </summary>
        /// <param name="p_ColumnIndex"></param>
        /// <returns></returns>
        public override Cells.ICellVirtual[] GetCellsAtColumn(int p_ColumnIndex)
        {
            Cells.ICellVirtual[] l_Cells = new Cells.ICellVirtual[Rows.Count];

            for (int r = 0; r < Rows.Count;)
            {
                Cells.ICell l_Cell = this[r, p_ColumnIndex];
                if (l_Cell != null &&
                    l_Cell.Range.Start == new Position(r, p_ColumnIndex))
                {
                    l_Cells[r] = l_Cell;
                    r         += l_Cell.RowSpan;
                }
                else
                {
                    l_Cells[r] = null;
                    r++;
                }
            }

            return(l_Cells);
        }
예제 #28
0
        /// <summary>
        /// Returns all the cells at specified row position
        /// </summary>
        /// <param name="p_RowIndex"></param>
        /// <returns></returns>
        public override Cells.ICellVirtual[] GetCellsAtRow(int p_RowIndex)
        {
            Cells.ICellVirtual[] l_Cells = new Cells.ICellVirtual[Columns.Count];

            for (int c = 0; c < Columns.Count;)
            {
                Cells.ICell l_Cell = this[p_RowIndex, c];
                if (l_Cell != null &&
                    l_Cell.Range.Start == new Position(p_RowIndex, c))
                {
                    l_Cells[c] = l_Cell;
                    c         += l_Cell.ColumnSpan;
                }
                else
                {
                    l_Cells[c] = null;
                    c++;
                }
            }

            return(l_Cells);
        }
예제 #29
0
        private void DirectSetCell(Position position, Cells.ICell cell)
        {
            //[email protected]: Error check done first.
            if (position.Column >= Columns.Count)
            {
                throw new ArgumentException(string.Format(
                                                "Grid has only {0} columns, you tried to insert cell into position {1}." +
                                                "You should probably call Redim on grid to increase it's column size",
                                                Columns.Count, position.ToString()));
            }
            GridColumn col = Columns[position.Column] as GridColumn;

            if (col == null)
            {
                return;
            }

            GridRow row = Rows[position.Row];

            if (row == null)
            {
                return;
            }

            if (OptimizeMode == CellOptimizeMode.ForRows)
            {
                row[col] = cell;
            }
            else if (OptimizeMode == CellOptimizeMode.ForColumns)
            {
                col[row] = cell;
            }
            else
            {
                throw new SourceGridException("Invalid OptimizeMode");
            }
        }
예제 #30
0
		/// <summary>
		/// Fired when calling SortRangeRows method. If the range contains all the columns this method move directly the row object otherwise move each cell.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnSortingRangeRows(SortRangeRowsEventArgs e)
		{
			base.OnSortingRangeRows(e);

			if (CustomSort)
				return;

			if (e.KeyColumn > e.Range.End.Column && e.KeyColumn < e.Range.Start.Column)
				throw new ArgumentException("Invalid range", "e.KeyColumn");

			System.Collections.IComparer cellComparer = e.CellComparer;
			if (cellComparer == null)
				cellComparer = new ValueCellComparer();

			//Sort all the columns (in this case I move directly the row object)
			if (e.Range.ColumnsCount == ColumnsCount)
			{
				RowInfo[] rowInfoToSort = new RowInfo[e.Range.End.Row-e.Range.Start.Row+1];
				Cells.ICell[] cellKeys = new Cells.ICell[e.Range.End.Row-e.Range.Start.Row+1];

				int zeroIndex = 0;
				for (int r = e.Range.Start.Row; r <= e.Range.End.Row;r++)
				{
					cellKeys[zeroIndex] = this[r, e.KeyColumn];

					rowInfoToSort[zeroIndex] = Rows[r];
					zeroIndex++;
				}

				Array.Sort(cellKeys, rowInfoToSort, 0, cellKeys.Length, cellComparer);

				//Apply sort
				if (e.Ascending)
				{
					for (zeroIndex = 0; zeroIndex < rowInfoToSort.Length; zeroIndex++)
					{
						Rows.Swap( rowInfoToSort[zeroIndex].Index, e.Range.Start.Row + zeroIndex);
					}
				}
				else //desc
				{
					for (zeroIndex = rowInfoToSort.Length-1; zeroIndex >= 0; zeroIndex--)
					{
						Rows.Swap( rowInfoToSort[zeroIndex].Index, e.Range.End.Row - zeroIndex);
					}
				}
			}
			else //sort only the specified range
			{
				Cells.ICell[][] l_RangeSort = new Cells.ICell[e.Range.End.Row-e.Range.Start.Row+1][];
				Cells.ICell[] l_CellsKeys = new Cells.ICell[e.Range.End.Row-e.Range.Start.Row+1];

				int zeroRowIndex = 0;
				for (int r = e.Range.Start.Row; r <= e.Range.End.Row;r++)
				{
					l_CellsKeys[zeroRowIndex] = this[r, e.KeyColumn];

					int zeroColIndex = 0;
					l_RangeSort[zeroRowIndex] = new Cells.ICell[e.Range.End.Column-e.Range.Start.Column+1];
					for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
					{
						l_RangeSort[zeroRowIndex][zeroColIndex] = this[r,c];
						zeroColIndex++;
					}
					zeroRowIndex++;
				}

				Array.Sort(l_CellsKeys, l_RangeSort, 0, l_CellsKeys.Length, cellComparer);

				//Apply sort
				zeroRowIndex = 0;
				if (e.Ascending)
				{
					for (int r = e.Range.Start.Row; r <= e.Range.End.Row;r++)
					{
						int zeroColIndex = 0;
						for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
						{
							RemoveCell(r,c);//rimuovo qualunque cella nella posizione corrente
							Cells.ICell tmp = l_RangeSort[zeroRowIndex][zeroColIndex];

							if (tmp!=null && tmp.Grid!=null && tmp.Range.Start.Row>=0 && tmp.Range.Start.Column>=0) //verifico che la cella sia valida
								RemoveCell(tmp.Range.Start.Row, tmp.Range.Start.Column);//la rimuovo dalla posizione precedente

							this[r,c] = tmp;
							zeroColIndex++;
						}
						zeroRowIndex++;
					}
				}
				else //desc
				{
					for (int r = e.Range.End.Row; r >= e.Range.Start.Row;r--)
					{
						int zeroColIndex = 0;
						for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
						{
							RemoveCell(r,c);//rimuovo qualunque cella nella posizione corrente
							Cells.ICell tmp = l_RangeSort[zeroRowIndex][zeroColIndex];

							if (tmp!=null && tmp.Grid!=null && tmp.Range.Start.Row >= 0 && tmp.Range.Start.Column >= 0) //verifico che la cella sia valida
								RemoveCell(tmp.Range.Start.Row, tmp.Range.Start.Column);//la rimuovo dalla posizione precedente

							this[r,c] = tmp;
							zeroColIndex++;
						}
						zeroRowIndex++;
					}
				}
			}
		}
예제 #31
0
        /// <summary>
        /// Fired when calling SortRangeRows method. If the range contains all the columns this method move directly the row object otherwise move each cell.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSortingRangeRows(SortRangeRowsEventArgs e)
        {
            base.OnSortingRangeRows(e);

            if (CustomSort)
            {
                return;
            }

            if (e.KeyColumn > e.Range.End.Column && e.KeyColumn < e.Range.Start.Column)
            {
                throw new ArgumentException("Invalid range", "e.KeyColumn");
            }

            System.Collections.IComparer cellComparer = e.CellComparer;
            if (cellComparer == null)
            {
                cellComparer = new ValueCellComparer();
            }

            //Sort all the columns (in this case I move directly the row object)
            if (e.Range.ColumnsCount == ColumnsCount)
            {
                RowInfo[]     rowInfoToSort = new RowInfo[e.Range.End.Row - e.Range.Start.Row + 1];
                Cells.ICell[] cellKeys      = new Cells.ICell[e.Range.End.Row - e.Range.Start.Row + 1];

                int zeroIndex = 0;
                for (int r = e.Range.Start.Row; r <= e.Range.End.Row; r++)
                {
                    cellKeys[zeroIndex] = this[r, e.KeyColumn];

                    rowInfoToSort[zeroIndex] = Rows[r];
                    zeroIndex++;
                }

                Array.Sort(cellKeys, rowInfoToSort, 0, cellKeys.Length, cellComparer);

                //Apply sort
                if (e.Ascending)
                {
                    for (zeroIndex = 0; zeroIndex < rowInfoToSort.Length; zeroIndex++)
                    {
                        Rows.Swap(rowInfoToSort[zeroIndex].Index, e.Range.Start.Row + zeroIndex);
                    }
                }
                else                 //desc
                {
                    for (zeroIndex = rowInfoToSort.Length - 1; zeroIndex >= 0; zeroIndex--)
                    {
                        Rows.Swap(rowInfoToSort[zeroIndex].Index, e.Range.End.Row - zeroIndex);
                    }
                }
            }
            else             //sort only the specified range
            {
                Cells.ICell[][] l_RangeSort = new Cells.ICell[e.Range.End.Row - e.Range.Start.Row + 1][];
                Cells.ICell[]   l_CellsKeys = new Cells.ICell[e.Range.End.Row - e.Range.Start.Row + 1];

                int zeroRowIndex = 0;
                for (int r = e.Range.Start.Row; r <= e.Range.End.Row; r++)
                {
                    l_CellsKeys[zeroRowIndex] = this[r, e.KeyColumn];

                    int zeroColIndex = 0;
                    l_RangeSort[zeroRowIndex] = new Cells.ICell[e.Range.End.Column - e.Range.Start.Column + 1];
                    for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
                    {
                        l_RangeSort[zeroRowIndex][zeroColIndex] = this[r, c];
                        zeroColIndex++;
                    }
                    zeroRowIndex++;
                }

                Array.Sort(l_CellsKeys, l_RangeSort, 0, l_CellsKeys.Length, cellComparer);

                //Apply sort
                zeroRowIndex = 0;
                if (e.Ascending)
                {
                    for (int r = e.Range.Start.Row; r <= e.Range.End.Row; r++)
                    {
                        int zeroColIndex = 0;
                        for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
                        {
                            RemoveCell(r, c);                           //rimuovo qualunque cella nella posizione corrente
                            Cells.ICell tmp = l_RangeSort[zeroRowIndex][zeroColIndex];

                            if (tmp != null && tmp.Grid != null && tmp.Range.Start.Row >= 0 && tmp.Range.Start.Column >= 0) //verifico che la cella sia valida
                            {
                                RemoveCell(tmp.Range.Start.Row, tmp.Range.Start.Column);                                    //la rimuovo dalla posizione precedente
                            }
                            this[r, c] = tmp;
                            zeroColIndex++;
                        }
                        zeroRowIndex++;
                    }
                }
                else                 //desc
                {
                    for (int r = e.Range.End.Row; r >= e.Range.Start.Row; r--)
                    {
                        int zeroColIndex = 0;
                        for (int c = e.Range.Start.Column; c <= e.Range.End.Column; c++)
                        {
                            RemoveCell(r, c);                           //rimuovo qualunque cella nella posizione corrente
                            Cells.ICell tmp = l_RangeSort[zeroRowIndex][zeroColIndex];

                            if (tmp != null && tmp.Grid != null && tmp.Range.Start.Row >= 0 && tmp.Range.Start.Column >= 0) //verifico che la cella sia valida
                            {
                                RemoveCell(tmp.Range.Start.Row, tmp.Range.Start.Column);                                    //la rimuovo dalla posizione precedente
                            }
                            this[r, c] = tmp;
                            zeroColIndex++;
                        }
                        zeroRowIndex++;
                    }
                }
            }
        }