Question

Assume that I have a DataGridView which is populated by a number of different strings (different length, numbers and plain text) in Cells.

Want I want to do is to copy and paste these strings, which could be any selection of Cells.

My approach to copy is:

if (e.Control && e.KeyCode == Keys.C)
{
    // copy
    DataGridViewSelectedCellCollection tmpCells = this.MyDataGridView.SelectedCells;
    Clipboard.SetDataObject(tmpCells);
 }

Which is working properly.

My approach to paste is:

if (e.Control && e.KeyCode == Keys.V)
{
    // paste
    IDataObject dataInClipboard = Clipboard.GetDataObject();
    string stringInClipboard = (string)dataInClipboard.GetData(DataFormats.Text);
    char[] rowSplitter = { '\r', '\n' };
    char[] columnSplitter = { '\t' };
    string[] rowsInClipboard = stringInClipboard.Split(rowSplitter, StringSplitOptions.RemoveEmptyEntries);

    int r1 = this.MyDataGridView.SelectedCells[0].RowIndex;
    int c1 = this.MyDataGridView.SelectedCells[0].ColumnIndex;
    int r2 = this.MyDataGridView.SelectedCells[this.MyDataGridView.SelectedCells.Count-1].RowIndex;
    int c2 = this.MyDataGridView.SelectedCells[this.MyDataGridView.SelectedCells.Count-1].ColumnIndex;

    int r = Math.Min(r1, r2);   // Do not care if selection was taken by drag mouse up or down, always start from min
    int c = Math.Min(c1, c2);   // Do not care if selection was taken by drag mouse left or right, always start from min

    for (int iRow = 0; iRow < rowsInClipboard.Length; ++iRow )
    {
        string[] valuesInRow = rowsInClipboard[iRow].Split(columnSplitter);

        for (int iCol = 0; iCol < valuesInRow.Length; ++iCol )
        {
            if (this.MyDataGridView.ColumnCount-1 >= c + iCol)
            {

                DataGridViewCell DGVC = (this.MyDataGridView.Rows[r + iRow].Cells[c + iCol]);

                DGVC.Value = valuesInRow[iCol];

             }
          }
     }
  }
}

Which works fine UNLESS the string itself DOES NOT contain any delimiter I specified with rowSplitter and columnSplitter. But this unfortunately is the case very often. It then separates the string and expands it to the next cell.

Example:

Cell[n] = {"This string contains a new line delimiter \n but should use only one cell."}

Will be pasted to:

Cell[n] = {"This string contains a new line delimiter"}; 
Cell[n+1] = {"but should use only one cell."}

So my question is: is it possible to restore the DataGridViewSelectedCellCollection as it was copied to the clipboard before? Just casting from object to DataGridViewSelectedCellCollection will not work:

DataGridViewSelectedCellCollection DGSCC = (DataGridViewSelectedCellCollection)dataInClipboard; // compiles, but throws exception at runtime

Do I have any other option but parsing each string by a defined formatting?

Était-ce utile?

La solution

You will have to define own format for clipboard, which will do what default one can't do for you.

Simplest solution in this specific case is to convert multi-line breaks into \n and then convert back when you paste, but in any case it means no more

DataGridViewSelectedCellCollection tmpCells = this.MyDataGridView.SelectedCells;
Clipboard.SetDataObject(tmpCells);

but

DataGridViewSelectedCellCollection tmpCells = this.MyDataGridView.SelectedCells;
string result = "";
foreach(DataGridViewCell cell in tempCells)
    // ... try to replicate what default clipboard text representation does
// change line breaks
Clipboard.SetDataObject(result.Replace("\xd\xa", "\\n"));

and paste will be:

IDataObject dataInClipboard = Clipboard.GetDataObject();
string stringInClipboard = dataInClipboard.GetData(DataFormats.Text).ToString().Replace("\\n", "\xd\xa");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top