WPF Datagrid:将其他行复制到剪贴板

mht*_*ttk 5 wpf clipboard datagrid

我正在使用WPF Datagrid,我正在尝试增强/更改复制和粘贴机制.

当用户选择一些单元格然后按CTRL + C时,底层控件能够捕获CopyingRowClipboardContent事件.

 this.mainDataGrid.CopyingRowClipboardContent 
              += this.DatagridOnCopyingRowClipboardContent;
Run Code Online (Sandbox Code Playgroud)

在这种方法中,一些单元格被添加到标题和行中,因此产生"更宽"的网格.

    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"));
    }
Run Code Online (Sandbox Code Playgroud)

此时我被卡住了,因为我试图在标题之前添加一行,在最后一行之后添加行(见下图).

有任何想法吗?建议?

请注意我对MVVM的方式不感兴趣.

在此输入图像描述

Dam*_*cus 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);
    }
Run Code Online (Sandbox Code Playgroud)