2013-12-20 4 views
2

Предположим, что у меня есть DataGridView, который заполнен рядом различных strings (разные длины, цифры и обычный текст) в ячейках.Копировать + Вставить DataGridViewSelectedCellCollection в/из буфера обмена

Хочу, чтобы я хотел скопировать и вставить эти строки, которые могут быть любым выбором Ячейки.

Мой подход к копия является:

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

Который работает должным образом.

Мой подход к паста является:

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]; 

      } 
      } 
    } 
    } 
} 

Который работает отлично UNLESS сама строка НЕ содержать любой разделитель, который указал с rowSplitter и columnSplitter. Но это, к сожалению, очень часто. Затем он отделяет строку и расширяет ее до следующей ячейки.

Пример:

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

будет вставлено:

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

Так что мой вопрос: можно ли восстановить DataGridViewSelectedCellCollection, как он был скопирован в буфер обмена раньше? Просто литье из object в DataGridViewSelectedCellCollection не будет работать:

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

У меня есть какой-либо другой выбор, кроме разбора каждой строки по определенному форматированию?

ответ

1

Вам нужно будет определить собственный формат для буфера обмена, который будет делать то, что по умолчанию для вас невозможно.

решение Простейшие в данном конкретном случае заключается в преобразовании нескольких разрывов строк в \n, а затем преобразовать обратно, когда вы паста, но в любом случае это означает не более

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

но

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")); 

и паста будет:

IDataObject dataInClipboard = Clipboard.GetDataObject(); 
string stringInClipboard = dataInClipboard.GetData(DataFormats.Text).ToString().Replace("\\n", "\xd\xa"); 
+0

Отличная идея, проста в использовании! – fiscblog

Смежные вопросы