XamDataGridでFieldGroupを使って列をグループ化していると、クリップボード機能でコピーした際に、既定の実装ではコピー結果の列順が画面の表示順と一致しないことがあります。本記事では、ClipboardCopyingイベントを使って選択範囲を独自に文字列化し、常に画面の表示順通りにクリップボードへコピーする方法を紹介します。

XamDataGrid の設定

まずXamDataGridでクリップボード操作を有効にし、ClipboardCopyingイベントをハンドラーに割り当てます。今回のポイントは、FieldGroupを使って列をグループ化している点です。

<igWPF:XamDataGrid x:Name="xamDataGrid1" DataSource="{Binding}" ClipboardCopying="xamDataGrid1_ClipboardCopying">
    <igWPF:XamDataGrid.FieldLayoutSettings>
        <igWPF:FieldLayoutSettings AutoGenerateFields="False" AllowClipboardOperations="All"/>
    </igWPF:XamDataGrid.FieldLayoutSettings>
    <igWPF:XamDataGrid.FieldLayouts>
        <igWPF:FieldLayout>
            <igWPF:Field Name="AAA" />
            <igWPF:FieldGroup Label="BBB">
                <igWPF:Field Name="B1"/>
                <igWPF:Field Name="B2"/>
            </igWPF:FieldGroup>
            <igWPF:Field Name="CCC" />
            <igWPF:FieldGroup Label="DDD">
                <igWPF:Field Name="D1"/>
                <igWPF:Field Name="D2"/>
            </igWPF:FieldGroup>
            <igWPF:Field Name="EEE" />
        </igWPF:FieldLayout>
    </igWPF:XamDataGrid.FieldLayouts>
</igWPF:XamDataGrid>

例えば、AAA、BBB(B1・B2)、CCC、DDD(D1・D2)、EEEの順に列が並んだ画面で、値が「A0、B0、B1、C0、D0、D1、E0」の1行目を選択してコピーし、MS Excelにペーストすると、既定の実装ではFieldGroup外の列(AAA・CCC・EEE)が先にまとめられ、FieldGroup内の列(BBB・DDD)が後に続く「A0、C0、E0、B0、B1、D0、D1」という順序でペーストされてしまい、画面の表示順とは異なる結果になります。

ClipboardCopying イベントの処理

ClipboardCopyingイベントでは、既定のコピー処理をキャンセルし(e.Cancel = true)、選択されているセル(SelectedItems.Cells)またはレコード(SelectedItems.Records)を画面の表示順に走査しながら独自にタブ・改行区切りの文字列を組み立て、Clipboard.SetTextでクリップボードに設定します。こうすることで、FieldGroupの有無に関わらず、常に見た目通りの順序でコピーが行われるようになります。

private void xamDataGrid1_ClipboardCopying(object sender, Infragistics.Windows.DataPresenter.Events.ClipboardCopyingEventArgs e)
{
    if (sender is not XamDataGrid xamDataGrid)
    {
        return;
    }

    var strBuilder = new StringBuilder();

    var selectedCells = xamDataGrid.SelectedItems.Cells;
    var selectedCellCount = selectedCells.Count;

    if (selectedCellCount > 0)
    {
        for (var i = 0; i < selectedCellCount; i++)
        {
            var currentCell = selectedCells[i];

            if (i > 0)
            {
                var previousCell = selectedCells[i - 1];

                if (previousCell.Record.Index != currentCell.Record.Index)
                {
                    strBuilder.Append("\r\n");
                }
                else
                {
                    strBuilder.Append('\t');
                }
            }

            strBuilder.Append(currentCell.Value);
        }
    }
    else
    {
        foreach (DataRecord rec in xamDataGrid.SelectedItems.Records)
        {
            var cells = rec.Cells;
            var cellCount = cells.Count;

            for (var i = 0; i < cellCount; i++)
            {
                if (i > 0)
                {
                    strBuilder.Append('\t');
                }

                strBuilder.Append(cells[i].Value);
            }

            strBuilder.Append("\r\n");
        }
    }

    Clipboard.SetText(strBuilder.ToString());
    e.Cancel = true;
}

実行結果

サンプルを実行し、先ほどと同じ1行目を選択してコピーした後、MS Excelにペーストすると、今度はFieldGroupで並べた列の順序通り「A0、B0、B1、C0、D0、D1、E0」の順でデータが貼り付けられ、画面の見た目通りの結果が得られます。

Tagged:

製品について

Ultimate UI for WPF