wpf icon indicating copy to clipboard operation
wpf copied to clipboard

WPF DataGrid HTML clipboard data faulty

Open kniessen opened this issue 11 months ago • 8 comments

Description

The HTML fragment DataGrid puts into the clipboard is not accepted by other applications.

It appears that the fragment's offsets (StartHTML/EndHTML/StartFragment/EndFragment) do not match the content.

Reproduction Steps

Select all data in a DataGrid, copy and then paste to Excel.

Expected behavior

Excel (or other application) correctly accepts HTML data from DatGrid in clipboard.

Actual behavior

Application cannot interpret and paste HTML data copied from DataGrid but display error.

Regression?

Error was introduced with #8519.

Known Workarounds

  1. Derive DataGrid subclass and override OnExecutedCopy:
        protected override void OnExecutedCopy(ExecutedRoutedEventArgs args)
        {
            base.OnExecutedCopy(args);

            String htmlData = Clipboard.GetData(DataFormats.Html) as String;
            htmlData = htmlData.Replace("\r\n\r\n", "\r\n");
            Clipboard.SetData(DataFormats.Html, htmlData);
        }

2. Manually select csv or other format when pasting data copied from DataGrid in other applications.

### Impact

High impact at my company's backoffice which uses copy/paste to Excel intensely. On a more general scale, probably low.

### Configuration

.Net 9 Win11

### Other information

The problem with the wrong offsets is a result of double CR/LFs between the header items in Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGridClipboardHelper.cs (lines 86-102) - remove those and everything works as before.

kniessen avatar Feb 19 '25 10:02 kniessen

Cc @halgab

The origin code: https://github.com/dotnet/wpf/pull/8519/files#diff-1e969bd11b05c363a95985d0554e02082433d0d7a563a91c72392b6fe23a6d9cL18

The code in https://github.com/dotnet/wpf/pull/8519 : https://github.com/dotnet/wpf/pull/8519/files#diff-1e969bd11b05c363a95985d0554e02082433d0d7a563a91c72392b6fe23a6d9cR87-R116


@kniessen I try fix this issues in https://github.com/dotnet/wpf/pull/10477 .

lindexi avatar Feb 19 '25 11:02 lindexi

So sorry for the bug. I thought I had fixed manually this automatic addition of 2 new lines instead if one everywhere but I guess this one slipped through...

halgab avatar Feb 25 '25 21:02 halgab

@halgab could you please review https://github.com/dotnet/wpf/pull/10477 so we can get rid of this bug?

koriandus avatar Jun 05 '25 08:06 koriandus

Sure. I've just commented on the PR per your request

halgab avatar Jun 07 '25 20:06 halgab

@halgab Need I do any changes?

lindexi avatar Jun 09 '25 01:06 lindexi

I don't think so. Thanks again for sorting out my mess

halgab avatar Jun 11 '25 21:06 halgab

@halgab Don't worry. This is just a small problem.

lindexi avatar Jun 12 '25 00:06 lindexi

I'm looking forward to when this is released.

I'm not sure if the original workaround:

var htmlData = Clipboard.GetData(DataFormats.Html) as string;
htmlData = htmlData.Replace("\r\n\r\n", "\r\n");
Clipboard.SetData(DataFormats.Html, htmlData);

always cleared other data formats, so pasting the string contents would no-op (ex into notepad), so I had to flip to this:

var frozenOLEClipboardData = Clipboard.GetDataObject();
var htmlData = frozenOLEClipboardData.GetData(DataFormats.Html) as string;
htmlData = htmlData.Replace("\r\n\r\n", "\r\n");
var clipboardData = new DataObject();
clipboardData.SetData(DataFormats.Text, frozenOLEClipboardData.GetData(DataFormats.Text));
clipboardData.SetData(DataFormats.UnicodeText, frozenOLEClipboardData.GetData(DataFormats.UnicodeText));
clipboardData.SetData(DataFormats.StringFormat, frozenOLEClipboardData.GetData(DataFormats.StringFormat));
clipboardData.SetData(DataFormats.CommaSeparatedValue, frozenOLEClipboardData.GetData(DataFormats.CommaSeparatedValue));
clipboardData.SetData(DataFormats.Html, htmlData);
Clipboard.SetDataObject(clipboardData, true);

to preserve the various clipboard formats/avoid getting an System.InvalidOperationException with the message "Cannot SetData on a frozen OLE data object." (Happened when I tried overwriting the HTML on the object I got from Clipboard.GetDataObject()).

I was using PowerShell to see what was on the clipboard/help troubleshoot:

function Interrogate-Clipboard {
    Add-Type -AssemblyName PresentationCore

    $clipboard = [Windows.Clipboard]::GetDataObject()

    if (-not $clipboard) {
        Write-Host "Clipboard is empty or unavailable." -ForegroundColor Yellow
        return
    }

    $dataFormats = $clipboard.GetFormats()
    Write-Host "Data formats available on the clipboard:"
    $dataFormats | ForEach-Object { Write-Host "- $_" }

    foreach ($format in $dataFormats) {
        try {
            $data = $clipboard.GetData($format)
            Write-Host "`nFormat: $format"
            Write-Host "Data Type: $($data.GetType().FullName)"
            Write-Host "Data Preview: $data"
        } catch {
            Write-Host "`nFormat: $format"
            Write-Host "Error retrieving data: $_" -ForegroundColor Red
        }
    }
}

I could have sworn the original workaround kept the string/unicodetext/csv options on the clipboard, but maybe I just focused on excel and forgot to check the others.

sir-wilhelm avatar Sep 11 '25 16:09 sir-wilhelm