Search code examples
c#winformsdatagridviewcopy-pastenul

Why won't copy paste work when NUL character is present in datagridview selection?


Why will any form of copy/paste of datagridview not work if there are "NUL" characters (i.e. ASCII code = 0) present? If there are "NUL" characters present in data, the datagridview displays them as spaces but will not copy (or at least, not paste) beyond an instance of them. I'm not sure if I've found a bug or if I simply am not understanding clipboard/copy/paste behavior. Both manual copy/paste and programmatic methods produce the same results. If one manually selects, it will appear to select multiple rows but when one pastes, only the data before the first instance of "NUL" character is pasted. The rest of the data on that row and all other rows is not pasted.

None of the row/edit settings seem to matter. The method of generating data in the cells does not seem to matter. I searched Google and S.O. For an answer to no avail. Yes, I did see the S.O. posts Copy string data with NULL character inside string to char array and NULL in a string can't copy contents after NUL and some similar posts but none answer the question--they only provide workarounds involving replacement of NUL characters. I'm hoping to understand the "why" as well as find a way to copy/paste including NUL characters.

I have created a purely test scenario. Apologies if I have included too much. I'm not entirely sure what is required/relevant so I erred on side of too much.

using System;
using System.Data;
using System.Windows.Forms;

namespace GQ
{
    public partial class frmTestOfDataGrid : Form
    {
        public frmTestOfDataGrid()
        {
            InitializeComponent();
        }

        private void buttonRunTest_Click(object sender, EventArgs e)
        { 
            BindingSource myBindingSource = new BindingSource();
            myBindingSource.DataSource = CreateTestDataTable();
            dataGridView1.DataSource = myBindingSource;
            dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }
        private DataTable CreateTestDataTable()
        {
            char Nul = (char)0;
            string myTestString1 = "The Nul characters are between these >" + Nul + Nul + "< and you can't copy anything after them.";
            string myTestString2 = "Second line of test data will not end up being copied to clipboard if above Nul characters are included in selection.";
            DataTable tbl = new DataTable();
            tbl.Columns.Add("RowIndex", typeof(Int32));
            tbl.Columns.Add("RowValue", typeof(String));
            DataRow dr1 = tbl.NewRow();
            dr1[0] = 0;
            dr1[1] = myTestString1;
            tbl.Rows.Add(dr1);
            DataRow dr2 = tbl.NewRow();
            dr2[0] = 1Y;
            dr2[1] = myTestString2;
            tbl.Rows.Add(dr2);
            return tbl;
        }

        private void buttonCopyToClipboard_Click(object sender, EventArgs e)
        {
            if (this.dataGridView1
                .GetCellCount(DataGridViewElementStates.Selected) > 0)
            {
                Clipboard.SetDataObject(this.dataGridView1.GetClipboardContent());
            }
        }
    }
}
namespace GQ
{
    partial class frmTestOfDataGrid
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.buttonRunTest = new System.Windows.Forms.Button();
            this.buttonCopyToClipboard = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AllowUserToDeleteRows = false;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(10, 43);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.ReadOnly = true;
            this.dataGridView1.Size = new System.Drawing.Size(963, 313);
            this.dataGridView1.TabIndex = 0;
            // 
            // buttonRunTest
            // 
            this.buttonRunTest.Location = new System.Drawing.Point(753, 371);
            this.buttonRunTest.Name = "buttonRunTest";
            this.buttonRunTest.Size = new System.Drawing.Size(146, 27);
            this.buttonRunTest.TabIndex = 1;
            this.buttonRunTest.Text = "Run Test";
            this.buttonRunTest.UseVisualStyleBackColor = true;
            this.buttonRunTest.Click += new System.EventHandler(this.buttonRunTest_Click);
            // 
            // buttonCopyToClipboard
            // 
            this.buttonCopyToClipboard.Location = new System.Drawing.Point(753, 403);
            this.buttonCopyToClipboard.Name = "buttonCopyToClipboard";
            this.buttonCopyToClipboard.Size = new System.Drawing.Size(146, 27);
            this.buttonCopyToClipboard.TabIndex = 2;
            this.buttonCopyToClipboard.Text = "Then Copy To Clipboard";
            this.buttonCopyToClipboard.UseVisualStyleBackColor = true;
            this.buttonCopyToClipboard.Click += new System.EventHandler(this.buttonCopyToClipboard_Click);
            // 
            // frmTestOfDataGrid
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(976, 442);
            this.Controls.Add(this.buttonCopyToClipboard);
            this.Controls.Add(this.buttonRunTest);
            this.Controls.Add(this.dataGridView1);
            this.Name = "frmTestOfDataGrid";
            this.Text = "frmTestOfDataGrid";
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
        }

        #endregion

        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.Button buttonRunTest;
        private System.Windows.Forms.Button buttonCopyToClipboard;
    }
}

Solution

  • (char)0 or '\0' is basically end of a string. That's why copy is not taking whatever there is afterwards.

    I put a newline in yr sentence it shows two charsenter image description here

    enter image description here

    And from the grid, it's still possible to copy/paste.

    enter image description here

    It's unusual to use ('\0'), I'm curious to know what's the reason behind using it?

    You can see a discussion on Why do we need to add a '\0' (null) at the end of a character array in C?