WPF数据表格:将额外行复制到剪贴板

5
我正在使用WPF数据网格,并试图改进/更改复制和粘贴机制。当用户选择一些单元格并按下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"));
    }

目前我遇到了困难,因为我想在标题之前添加一行,并在最后一行之后添加两行(如下图所示)。

有什么想法?建议?

请注意,我对这里的MVVM方式不感兴趣。

enter image description here


你画的这张图好棒啊,怎么画的? - Colonel Panic
2
谢谢。老派的笔和纸 ==> iPhone 拍照片 ==> 用 Paint.Net 裁剪和调整。整个过程可能不到一分钟。我使用右手是偶然的。 :) - mhttk
3个回答

4
这里有一段代码片段可能会对您有所帮助。 这个片段主要用于检索所有选定的数据,包括标题(我删除了 RowHeaders 部分,因为您显然不需要它)。 如果您有任何问题,请让我知道。 我留下了一些带有大写字母注释的部分:这是您应该添加自己数据的地方。 这种方法的好处是它直接与您的DataGrid ItemsSource 而不是 DataGridCell 一起使用。 主要原因是:如果您对格式化的数字使用 DataGridCell ,例如,您将无法获取实际值,而只能获得格式化后的值(假设您的源为14.49且 StringFormat 为N0,则仅复制14如果您使用“常规”方法)
   /// <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);
    }

这很有趣。所以你的方法实际上是完全绕过网格内的机制。 - mhttk
确切地说,我重新定义了复制/粘贴的行为,因为如上所述,默认行为并不能完全满足我的需求(我认为自然的是复制值而不仅仅是屏幕上显示的内容):/ - Damascus
你是怎样重写默认拷贝命令的行为的? - Alex Hope O'Connor

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则表示下一行。

0

我知道这是一个较旧的帖子,但我为了完整性而发布此解决方案。我找不到更近期的有关复制数据网格行到剪贴板的问题。使用Clipboard.SetData违背了ClipboardRowContent的意图。

对于我的需求,我重新将所需的行粘贴回e.ClipboardRowContent中。每个选定行的cell.Item就是我需要的所有信息。

提示:在使用e.ClipboardRowContent之后,如果没有执行e.ClipboardRowContent.Clear(),我会得到重复的内容。在清除之前,我使用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);

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接