2012-11-01 36 views
5

Sto lavorando con Datagrid WPF e sto cercando di migliorare/modificare il meccanismo di copia &.Datagrid WPF: copia ulteriori righe negli appunti

Quando l'utente seleziona alcune cellule e quindi premere CTRL + C, i controlli sottostanti è in grado di catturare il CopyingRowClipboardContent evento.

this.mainDataGrid.CopyingRowClipboardContent 
       += this.DatagridOnCopyingRowClipboardContent; 

In questo metodo, alcune celle vengono aggiunte all'intestazione e alle righe, risultando così in una griglia "più ampia".

private void DatagridOnCopyingRowClipboardContent(
     object sender, 
     DataGridRowClipboardEventArgs dataGridRowClipboardEventArgs) 
    { 
     // this is fired every time a row is copied 
     var allContent = dataGridRowClipboardEventArgs.ClipboardRowContent; 

     allContent.Insert(0, new DataGridClipboardCellContent(
              null, 
              this.mainDataGrid.Columns[0], 
              "new cell")); 
    } 

A questo punto mi sono bloccato perché sto cercando di aggiungere una riga aggiuntiva prima l'intestazione e due dopo l'ultima riga (vedi immagine sotto).

Qualche idea? Suggerimenti?

Si prega di notare che non mi interessa un modo MVVM di farlo qui.

enter image description here

+0

dolce pic come hai disegnarlo? –

+2

Grazie.Penna & carta vecchia scuola ==> foto iPhone ==> ritaglia e regola con Paint.Net. L'intero richiede probabilmente meno di un minuto. Il fatto che io usi la mia mano destra è incidentale. :) – mhttk

risposta

3

Ecco un frammento di codice che potrebbe aiutare. Questo snippet viene utilizzato principalmente per recuperare tutti i dati selezionati, comprese le intestazioni (ho rimosso la parte RowHeaders poiché apparentemente non ne hai bisogno). Se avete qualche domanda per favore fatemelo sapere. Ho lasciato alcune parti con commenti scritti in lettere maiuscole: è qui che è necessario aggiungere i propri dati La buona parte di questo approccio è che funziona direttamente con lo DataGrid di ItemsSource e NON con lo DataGridCell. Il motivo principale è che se si utilizza DataGridCell su un numero formattato, ad esempio, NON si otterrà il valore effettivo, ma solo quello formattato (ad esempio la propria fonte è 14.49 e il tuo StringFormat è N0, si copia solo 14 se si utilizza un modo "regolare")

/// <summary> 
    /// Handles DataGrid copying with headers 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void OnCopyingDataGrid(object sender, ExecutedRoutedEventArgs e) 
    { 
     // First step: getting the coordinates list of all cells selected 
     IList<Tuple<int, int>> cellsCoordinatesList = new List<Tuple<int, int>>(); 
     HashSet<int> rowList = new HashSet<int>(); 
     HashSet<int> columnList = new HashSet<int>(); 
     foreach (System.Windows.Controls.DataGridCellInfo cell in this.SelectedCells) 
     { 
      int column = cell.Column.DisplayIndex; 
      int row = this.Items.IndexOf(cell.Item); 
      cellsCoordinatesList.Add(new Tuple<int, int>(row, column)); 
      if (!rowList.Contains(row)) 
      { 
       rowList.Add(row); 
      } 
      if (!columnList.Contains(column)) 
      { 
       columnList.Add(column); 
      } 
     } 

     // Second step: Create the table to copy/paste 
     object[,] arrayToBeCopied = new object[rowList.Count, columnList.Count + 1]; 
     IList<string> colHead = this.ColumnHeaders.Cast<object>().Select(h => h.ToString()).ToList(); 
     for (int row = 0; row < arrayToBeCopied.GetLength(0); row++) 
     { 
      for (int column = 0; column < arrayToBeCopied.GetLength(1); column++) 
      { 
       if (row == 0) 
       { 
        arrayToBeCopied[row, column] = colHead[columnList.ElementAt(column - 1)]; 
       } 
       else 
       { 
        arrayToBeCopied[row, column] = // WHATEVER YOU WANT TO PUT IN THE CLIPBOARD SHOULD BE HERE. THIS SHOULD GET SOME PROPERTY IN YOUR ITEMSSOURCE 

       } 
      } 
     } 

     // Third step: Converting it into a string 
     StringBuilder sb = new StringBuilder(); 

     // HERE, ADD YOUR FIRST ROW BEFORE STARTING TO PARSE THE COPIED DATA 

     for (int row = 0; row < arrayToBeCopied.GetLength(0); row++) 
     { 
      for (int column = 0; column < arrayToBeCopied.GetLength(1); column++) 
      { 
       sb.Append(arrayToBeCopied[row, column]); 
       if (column < arrayToBeCopied.GetLength(1) - 1) 
       { 
        sb.Append("\t"); 
       } 
      } 
      sb.Append("\r\n"); 
     } 

     // AND HERE, ADD YOUR LAST ROWS BEFORE SETTING THE DATA TO CLIPBOARD 

     DataObject data = new DataObject(); 
     data.SetData(DataFormats.Text, sb.ToString()); 

     Clipboard.SetDataObject(data); 
    } 
+0

Questo è abbastanza interessante. Quindi il tuo approccio è di bypassare completamente il meccanismo all'interno della griglia. – mhttk

+0

Esattamente, ho ridefinito il comportamento di copia/incolla perché come ho spiegato sopra, quello predefinito non soddisfa completamente le mie esigenze (che considererei naturale, copiare i valori e non giustificare ciò che è scritto sullo schermo): / – Damascus

0

Stai cercando di copiare il contenuto in es. Excel dopo? Se è così, ecco quello che ho fatto:

/// <summary> 
/// Copy the data from the data grid to the clipboard 
/// </summary> 
private void copyDataOfMyDataGridToClipboard(object sender, EventArgs e) 
{ 
    // Save selection 
    int selectedRow = this.myDataGrid.SelectedRows[0].Index; 

    // Select data which you would like to copy 
    this.myDataGrid.MultiSelect = true; 
    this.myDataGrid.SelectAll(); 

    // Prepare data to be copied (that's the interesting part!) 
    DataObject myGridDataObject = this.myDataGrid.GetClipboardContent(); 
    string firstRow = "FirstRowCommentCell1\t"+ this.someDataInCell2 +"..\r\n"; 
    string lastTwoRows = "\r\nBottomLine1\t" + yourvariables + "\r\nBottomLine2"; 
    string concatenatedData = firstRow + myGridDataObject.GetText() + lastTwoRows; 

    // Copy into clipboard 
    Clipboard.SetDataObject(concatenatedData); 

    // Restore settings 
    this.myDataGrid.ClearSelection(); 
    this.myDataGrid.MultiSelect = false; 

    // Restore selection 
    this.myDataGrid.Rows[selectedRow].Selected = true; 
} 

Nel mio caso ho avuto qualche colpo di testa di statica che potrebbe facilmente essere concatenato con alcune variabili. Importante scrivere \t per la dichiarazione di un'altra cella, \r\n dichiara la riga successiva

0

Mi rendo conto che questo è un post più vecchio, ma pubblicizzo questa soluzione per completezza. Non sono riuscito a trovare una domanda più recente sulla copia di righe di dati graficamente negli appunti. L'uso di Clipboard.SetData smentisce l'intenzione di ClipboardRowContent.

Per le mie esigenze, sto ri-incollando nuovamente nella e.ClipboardRowContent la riga che desidero. La cella.Item contiene tutte le informazioni necessarie per ogni riga selezionata.

Suggerimento: stavo ottenendo i duplicati senza eseguire e.ClipboardRowContent.Clear(); dopo aver usato e.ClipboardRowContent. Stavo cancellando prima e usando DataGrid.SelectedItems per costruire le righe.

private void yourDataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e) 
{ 
var dataGridClipboardCellContent = new List<DataGridClipboardCellContent>(); 

string prevCell = ""; 
string curCell = ""; 

foreach (DataGridClipboardCellContent cell in e.ClipboardRowContent) 
{ 
    //Gives you access item.Item or item.Content here 
    //if you are using your struct (data type) you can recast it here curItem = (yourdatatype)item.Item;   
    curItem = cell.Item.ToString(); 

    if (curCell != prevCell) 
     dataGridClipboardCellContent.Add(new DataGridClipboardCellContent(item, item.Column, curCell)); 

    prevCell = curCell; 

} 
e.ClipboardRowContent.Clear(); 

//Re-paste back into e.ClipboardRowContent, additionally if you have modified/formatted rows to your liking 
e.ClipboardRowContent.AddRange(dataGridClipboardCellContent); 

}

Problemi correlati