5

WPF Datagridを使用していて、コピーと貼り付けのメカニズムを強化/変更しようとしています。

ユーザーがいくつかのセルを選択してからCTRL+Cを押すと、基になるコントロールはCopyingRowClipboardContentイベントをキャッチできます。

 this.mainDataGrid.CopyingRowClipboardContent 
              += this.DatagridOnCopyingRowClipboardContent;

この方法では、一部のセルがヘッダーと行の両方に追加されるため、「幅の広い」グリッドになります。

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

この時点で、ヘッダーの前に行を追加し、最後の行の後に2行追加しようとしているため、スタックしています(下の画像を参照)。

何か案は?提案?

ここでは、MVVMでそれを行う方法には興味がないことに注意してください。

ここに画像の説明を入力してください

4

3 に答える 3

4

これがあなたを助けるかもしれないコードスニペットです。このスニペットは主に、ヘッダーを含む、選択したすべてのデータを取得するために使用されます(RowHeaders明らかに必要ないため、パーツを削除しました)。ご不明な点がございましたら、お気軽にお問い合わせください。大文字で書かれたコメントをいくつか残しました。これは、独自のデータを追加する必要がある場所です。このアプローチの良い部分は、ではなく、自分のデータで直接機能するDataGridことItemsSourceですDataGridCell。主な理由は次のとおりです。DataGridCellたとえば、フォーマットされた数値を使用する場合、実際の値は取得されず、フォーマットされた数値のみが取得されます(たとえば、ソースが14.49で、StringFormatN0の場合、「通常の」方法)

   /// <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);
    }
于 2012-11-01T14:23:52.297 に答える
0

後でコンテンツをExcelなどにコピーしようとしていますか?もしそうなら、これが私がしたことです:

/// <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;
}

私の場合、いくつかの変数と簡単に連結できる静的ヘッダーがいくつかありました。書くことが重要なのは、\t別のセルを宣言するためのもので\r\nあり、次の行を宣言するためのものです

于 2014-02-07T10:48:46.790 に答える
0

私はこれが古い投稿であることを認識していますが、完全を期すためにこのソリューションを投稿しています。データグリッド行をクリップボードにコピーすることに関する最近の質問は見つかりませんでした。Clipboard.SetDataを使用すると、ClipboardRowContentの意図に反します。

必要に応じて、必要な行をe.ClipboardRowContentに再貼り付けします。cell.Itemは、選択した各行に必要なすべての情報です。

ヒント:e.ClipboardRowContent.Clear()を実行せずに重複を取得していました。e.ClipboardRowContentを使用した後。以前にクリアし、DataGrid.SelectedItemsを使用して行を作成していました。

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

}

于 2017-02-14T15:49:36.863 に答える