Search code examples
c#datagridviewdatatabledatagridviewlinkcolumn

Using a DataGridView to display the contents of a DataTable


I have a three-column DataTable that contains data that I need to use in various ways. The data in this DataTable comes from an Exchange Web Services call. The first column contains a row counter, the second contains the calendar name, and the third contains the calendar ID (which is a gibberish-looking string).

Displaying the raw data in a DataGridView is straightforward. But I want the DataGridView's second column to be different: instead of showing the calendar ID, I want to show some text ("Copy"), which, when clicked, will copy the calendar ID to the user's clipboard. Ideally it'd be styled like a hyperlink so the user knows it's not just some text in a box. This can conceivably be done with a DataGridViewLinkColumn type with an event handler.

The piece I'm having trouble with is populating the rows.

The following code sets up the columns just fine. But it doesn't populate the rows.

private static DataGridView CreateCalendarGridView(DataTable calendarTable)
{
    //Bind to the data source
    var calendarGridView = new DataGridView();
    //calendarGridView.AutoGenerateColumns = false;
    calendarGridView.AutoSize = false;
    calendarGridView.DataSource = calendarTable;
    calendarGridView.ColumnHeadersVisible = true;

    //Create counter column
    var counterColumn = new DataGridViewTextBoxColumn();
    counterColumn.DataPropertyName = COUNTER_COLUMN_NAME;
    counterColumn.Name = COUNTER_COLUMN_NAME;
    counterColumn.HeaderText = COUNTER_COLUMN_LABEL;

    //Create the Calendar name column
    var calendarNameColumn = new DataGridViewTextBoxColumn();
    calendarNameColumn.DataPropertyName = CALENDAR_COLUMN_NAME;
    calendarNameColumn.Name = CALENDAR_COLUMN_NAME;
    calendarNameColumn.HeaderText = CALENDAR_COLUMN_LABEL;

    //Create the Copy ID hyperlink column
    var copyIdLinkColumn = new DataGridViewLinkColumn();
    copyIdLinkColumn.DataPropertyName = ID_COLUMN_NAME;
    copyIdLinkColumn.Name = ID_COLUMN_NAME;
    copyIdLinkColumn.HeaderText = ID_COLUMN_NAME;
    copyIdLinkColumn.UseColumnTextForLinkValue = false;
    copyIdLinkColumn.TrackVisitedState = true;
    copyIdLinkColumn.LinkColor = Color.Blue;
    copyIdLinkColumn.VisitedLinkColor = Color.Purple;
    copyIdLinkColumn.LinkBehavior = LinkBehavior.HoverUnderline;
    copyIdLinkColumn.Text = "Copy";
    copyIdLinkColumn.UseColumnTextForLinkValue = true;

    calendarGridView.Columns.Add(counterColumn);
    calendarGridView.Columns.Add(calendarNameColumn);
    calendarGridView.Columns.Add(copyIdLinkColumn);



    //I feel like I'm missing a foreach row in the DataTable which would
    //create the row of cells, but I'm not sure, because isn't that the
    //point of the calendarGridView.DataSource assignment above?



    return calendarGridView;
}

I feel like if I could get the rows to fill, I could figure out how to change the behavior of the clickable third column.

What am I doing wrong?


Solution

  • I've made a working sample. Please choose as the answer if it helps you.

    .

    public partial class CalendarTable_Stage1 : Form
    {
        public CalendarTable_Stage1()
        {
            InitializeComponent();
    
            this.Controls.Add(makeDGV(DT));
        }
    
        DataTable DT
        {
            get
            {
                //Sample DataTable
                DataTable dtb = new DataTable();
                dtb.Columns.Add("empName");
                dtb.Columns.Add("empAddress");
                dtb.Rows.Add("Salim", "S.10, Santhi Nagar, Palakkad");
                dtb.Rows.Add("Manaf", "Thriveni, English church road, Palakkad");
                dtb.Rows.Add("Mohsin Khan", "Civil Nagar, Palakkad");
    
                return dtb;
            }
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
    
        }
    
        DataGridView makeDGV(DataTable dt)
        {
            DataGridView dgv = new DataGridView();
            // set dgv properties
    
            dgv.Size = new Size(300, 400);
            dgv.Columns.Add("empName", "Name");
    
            DataGridViewLinkColumn linkCol = new DataGridViewLinkColumn();
            linkCol.HeaderText = "Address";
            linkCol.Name = "empAddress";
            dgv.Columns.Add(linkCol);
            dgv.AllowUserToAddRows = false; // This will greatly increase adding speed
    
            dgv.CellContentClick += new DataGridViewCellEventHandler(dgv_CellContentClick);
    
            foreach (DataRow row in dt.Rows)
            {
                DataGridViewLinkCell_Mine linker = new DataGridViewLinkCell_Mine();
                linker.Value = "Copy";
                linker.data = row[1].ToString();
    
                DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
                cell.Value = row[0].ToString();
                dgv.Rows.Add();
    
                if (!dgv.AllowUserToAddRows)
                {
                    dgv[0, dgv.Rows.Count - 1] = cell;
                    dgv[1, dgv.Rows.Count - 1] = linker;
                }
                else
                {
                    dgv[0, dgv.Rows.Count - 2] = cell;
                    dgv[1, dgv.Rows.Count - 2] = linker;
                }
    
            }
    
            return dgv;
        }
    
        class DataGridViewLinkCell_Mine : DataGridViewLinkCell
        {
            public string data = "";
        }
    
        void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 1)
            {
                DataGridView dgv = (DataGridView)sender;
                DataGridViewLinkCell_Mine cell = (DataGridViewLinkCell_Mine)dgv[e.ColumnIndex, e.RowIndex];
                Clipboard.SetText(cell.data);
    
    
                MessageBox.Show(Clipboard.GetText());
            }
        }
    
    
    }