ReoGrid icon indicating copy to clipboard operation
ReoGrid copied to clipboard

Cell's tags are not deleted after darg-to-move cell

Open CmeFrog opened this issue 5 years ago • 6 comments

First off thanks for your great control. I have tried two other free controls and I found yours was the only one robust enough to do what I wanted. I am using your grid for a gantt chart in a project management app. I want the user to be able to move work (cells and ranges) around from one person (rows) to another or from one date (columns) to another. Work can only be moved around, no new work can be added. To accomplish this I first disabled cell editing by canceling the BeforeCellEdit event as recommended. However I found that data can also be added to a cell using the Fill Handle. If I select a cell or range its data can be added to other cells by dragging the fill handle. I tied to find a setting to disable the fill handle but was unable to find a mention of it anywhere. So I created a less than elegant workaround.

    bool AllowCellDataChangedEvent = true;
    unvell.ReoGrid.Cell cellFromFillHandle;

     private void FormRes_Load(object sender, EventArgs e)
    {
       timer1.Enabled = false;
}

    private void Sheet_BeforeRangeMove(object sender, BeforeCopyOrMoveRangeEventArgs e)
    {
        AllowCellDataChangedEvent = false;
    }

    private void Sheet_CellDataChanged(object sender, CellEventArgs e)
    {
        if (AllowCellDataChangedEvent)
        {
            AllowCellDataChangedEvent = false; // prevent infinite loop
            e.Cell.Data = string.Empty;
            AllowCellDataChangedEvent = true;
            cellFromFillHandle = e.Cell;
            timer1.Enabled = true;
            timer1.Start();
        }
    }
	
private void Sheet_AfterRangeMove(object sender, CopyOrMoveRangeEventArgs e)
    {
    // process the range move data
    .
    .
        AllowCellDataChangedEvent = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Grid1.CurrentWorksheet.SelectionRange = new RangePosition(cellFromFillHandle.Position);
        timer1.Enabled = false;
    }

First I create a class level variable called AllowCellDataChangedEvent. If this is true then my code in CellDataChanged is executed, otherwise it is skipped. The code in CellDataChanged is only to change the data for the cells that the fill handle was dragged over to empty string. The problem then became how to tell if the data change in CellDataChanged was from a range move (drag/drop) which I want to process normally or a fill handle copy which I want to negate with my code. To solve that I set the AllowCellDataChangedEvent variable to false inside the BeforeRangeMove event since it is raised before CellDataChanged. For range moves since AfterRangeMove is raised after CellDataChanged I set AllowCellDataChangedEvent back to true so fill handle copies will once again be negated.

The reason for the timer is that the selected cells after the fill handle copy were the original range (containing data) plus the cells that were supposed to be filled (now set to string.empty). This is an invalid selection so I wanted to reset the selected cells. I first tried to change the selection range in the CellDataChanged event but that did not work. So instead I start the timer with an interval of 10 and change the selection.

This is really a two part question. Is there an easier way to disable the fill handle? If not then could you consider adding a disable fill handle setting.

CmeFrog avatar Jul 04 '20 20:07 CmeFrog

@CmeFrog Do you have tried the Edit_DragSelectionToFillSerial settings.

worksheet.SetSettings(WorksheetSettings.Edit_DragSelectionToFillSerial, false);

jingwood avatar Jul 06 '20 12:07 jingwood

Thanks for the fix. It is exactly what I was looking for.

Another problem I faced and created what appears to be an adequate fix for was how to scroll to a cell and have that cell end up being located somewhere in the middle of the grid instead of at the margins.

    float currScrollBarXoffset = 0;
    float currScrollBarYoffset = 0;

    private void Grid1_WorksheetScrolled(object sender, WorksheetScrolledEventArgs e)
    {
        currScrollBarXoffset = e.OffsetX;
        currScrollBarYoffset = e.OffsetY;
    }

    private void ScrollToCell(CellPosition posTarget)
    {
        int posCol = GetScrollTargetColumn(posTarget.Col);
        int posRow = GetScrollTargetRow(posTarget.Row);
        Grid1.CurrentWorksheet.ScrollToCell(posRow, posCol);
    }

    private int GetScrollTargetRow(int rowTarget)
    {
        unvell.ReoGrid.Worksheet sheet = Grid1.CurrentWorksheet;
        int gridHeight = Grid1.ClientSize.Height;
        ushort rowHeight = sheet.GetRowHeight(0);
        int numRowsVisible = (int)(gridHeight / rowHeight);
        int numRowsToAdjust = (int)(numRowsVisible / 2);
        int adjTargetRow = 0;

        sheet.ScrollToCell(rowTarget, 0); // raises Grid1_WorksheetScrolled
        if (currScrollBarYoffset < 0)
                adjTargetRow = rowTarget - numRowsToAdjust; // Reogrid handles row indexes of less than 0
        else if (currScrollBarYoffset > 0)
            adjTargetRow = rowTarget + numRowsToAdjust; // Reogrid handles row indexes greater than RowCount
        return adjTargetRow;
    }

    private int GetScrollTargetColumn(int colTarget)
    {
        unvell.ReoGrid.Worksheet sheet = Grid1.CurrentWorksheet;
        int gridWidth = Grid1.ClientSize.Width;
        int rowHeaderWidth = sheet.RowHeaderWidth;
        int colWidth = sheet.GetColumnWidth(0);
        int numColsVisible = (int)((gridWidth - rowHeaderWidth) / colWidth);
        int numColsToAdjust = (int)(numColsVisible / 2);
        int adjTargetColumn = 0;

        sheet.ScrollToCell(0, colTarget);
        if (currScrollBarXoffset < 0)
                adjTargetColumn = colTarget + numColsToAdjust;
        else if (currScrollBarXoffset > 0)
            adjTargetColumn = colTarget - numColsToAdjust;
        return adjTargetColumn;
    }

Perhaps some of this logic could form a basis for a new ScrollToCellCentered method in Reogrid.

CmeFrog avatar Jul 06 '20 20:07 CmeFrog

Oops. Update to GetScrollTargetRow method--

        int numRowsVisible = (int)(gridHeight / rowHeight) - 1;// -1 for column header row

CmeFrog avatar Jul 06 '20 20:07 CmeFrog

One last update to account for if no scrolling necessary for target row or column.

In GetScrollTargetRow change to-- int adjTargetRow = rowTarget; In GetScrollTargetColumn change to-- int adjTargetColumn = colTarget;

CmeFrog avatar Jul 06 '20 21:07 CmeFrog

This issue was about when you move a cell(s) the cell's data is correctly moved to the new location. However all the data is not erased from the old location. The tag(s) of the old cell(s) still persist.

On Sat, Apr 3, 2021 at 9:01 PM Jingwood @.***> wrote:

Closed #350 https://github.com/unvell/ReoGrid/issues/350.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/unvell/ReoGrid/issues/350#event-4548210602, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB3SUGSJBPA4TIB4GIK22YTTG4YFFANCNFSM4OQRGMIA .

CmeFrog avatar Apr 04 '21 17:04 CmeFrog

Thanks! I will test the problem about tags.

jingwood avatar Apr 05 '21 00:04 jingwood