Anonymous
Anonymous

Reputation: 1988

Edit entire row in a DataGridView (not only one cell)

Could somebody advice how to do this?

Currently i have :

  1. DataGridView with four columns - Text1 | Text2 | EditButton | SaveButton
  2. When i click on the Text1 it becomes an editable field and i can change its value
  3. Then i try to edit Text2 but the click on this cell saves my changes in Text1

The issue is : when i try to edit second field (Text2) the first one (Text1) loses the focus, exits edit mode and saves changes that i made meanwhile i want to save all changes in a row simultaneously.

What i want to implement :

  1. I press EditButton and all cells becomes editable so i can change value of any cell in a row
  2. I change value of Text1, then value of Text2
  3. And only when i press SaveButton it saves made changes

The question is : how to keep all cells in a row in edit mode until i press specific button?

Upvotes: 2

Views: 5046

Answers (2)

Anonymous
Anonymous

Reputation: 1988

Ok, i know it may look a bit messy but this seems to be simplest solution i could come up to - display TextBox over each read only cell when grid is going to edit mode :

public void DisplayEditors(DataGridView grid, DataGridViewRow row)
        {
            foreach (DataGridViewCell cell in row.Cells)
            {
                if (cell.ReadOnly == false)
                {
                    var place = grid.GetCellDisplayRectangle(cell.ColumnIndex, cell.RowIndex, true);
                    var name = string.Format("EDITOR-{0}-{1}", cell.ColumnIndex, cell.RowIndex);
                    var editor = grid.Controls.Find(name, false).FirstOrDefault();

                    if (editor == null)
                    {
                        editor = new TextBox();

                        (editor as TextBox).Name = name;

                        grid.Controls.Add(editor);
                    }
                    else
                    {
                        editor.Show();
                    }

                    editor.Size = place.Size;
                    editor.Location = place.Location;
                    editor.Text = Convert.ToString(cell.Value);
                }
            }
        }

Upvotes: 0

igesan
igesan

Reputation: 66

Maybe you can use a custom DataGridView like this

public class CustomDGV : DataGridView
{
    private object _cellValue;
    private Dictionary<int, object[]> _pendingChanges;

    public CustomDGV()
    {
        _pendingChanges = new Dictionary<int, object[]>();
    }

    protected override void OnCellBeginEdit(DataGridViewCellCancelEventArgs e)
    {
        // Save the value of the cell before edit
        _cellValue = this[e.ColumnIndex, e.RowIndex].Value;

        // If there's already a pending change for that cell, display the edited value
        if (_pendingChanges.ContainsKey(e.RowIndex))
        {
            this[e.ColumnIndex, e.RowIndex].Value = _pendingChanges[e.RowIndex][e.ColumnIndex];
        }

        base.OnCellBeginEdit(e);
    }

    protected override void OnCellEndEdit(DataGridViewCellEventArgs e)
    {
        // Adds the edited value of the cell into a dictionary
        if (!_pendingChanges.ContainsKey(e.RowIndex))
        {
            _pendingChanges.Add(e.RowIndex, new object[this.ColumnCount]);
        }

        _pendingChanges[e.RowIndex][e.ColumnIndex] = this[e.ColumnIndex, e.RowIndex].Value;

        // Display the "old" value
        this[e.ColumnIndex, e.RowIndex].Value = _cellValue;
    }

    public void SavePendingChanges(int rowIndex)
    {
        if (_pendingChanges.ContainsKey(rowIndex))
        {
            // Gets the pending changes for that row
            var rowData = _pendingChanges[rowIndex];
            // Update every cell that's been edited
            for(int i = 0; i < rowData.Length; i++)
            {
                if (rowData[i] != null)
                    this[i, rowIndex].Value = rowData[i];
            }
            // Removes the pending changes from the dictionary once it's saved
            _pendingChanges.Remove(rowIndex);
        }
    }
}

And on CellContentClick you can call SavePendingChanges()

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex > -1 && e.RowIndex > -1)
    {
        if (e.ColumnIndex == 3) // Save button
        {
            dataGridView1.SavePendingChanges(e.RowIndex);
        }
    }
}

Upvotes: 2

Related Questions