[Solved] C# How to get all values of all rows in a dataGridView and pass it into another form


Here’s a minimal, but working example.

You can pass any type, to any method… for as long as the method is expecting the type as incoming parameter.

private void DoSomething(string withThisString)

In that method declaration, I declared that …

  1. the method is private aka accessible to this class only
  2. the method returns void aka does not return anything
  3. the method name is DoSomething
  4. the method is expecting a string parameter

You want to do something similar in your case. But you… you don’t want to be passing string as parameter, you want to pass DataGridViewRow… Actually no… you want to pass multiple rows so lets aggregate the rows in a List<DataGridViewRow> and we’ll pass a list of rows, instead of passing a single row.

List<DataGridViewRow> listofrows = new List<DataGridViewRow>();//we'll agregate our desired rows in this
//itterate through the rows of the DataGridView
foreach (DataGridViewRow item in dgv1.Rows)
{
    DataGridViewRow r = (DataGridViewRow)item.Clone();//clone the desired row
    //Oddly enough... cloning does not clone the values... So lets put the values back in their cells
    for (int i = 0; i < item.Cells.Count; i++)
    {
        r.Cells[i].Value = item.Cells[i].Value;
    }
    listofrows.Add(r);//add the row to the list
}

Also, you don’t want to be passing that parameter to DoSomething, you want to pass it to the method that is responsible of “initializing” the Form2.

By default, when you create a new form… the form constructor is written like this

public Form2()
{
    InitializeComponent();
}

public Form2() as we can see in the (), this method is not expecting any parameters to work. Actually, even if you wanted to, you couldn’t pass it anything because that method is not ready for anything. It just works alone

But you want to pass around some DataGridViewRow, so lets modify the method declaration a bit

public Form2(List<DataGridViewRow> dgvc = null)
{
    InitializeComponent();
}

public Form2(List<DataGridViewRow> dgvc = null) as we can see in the (), this method is now expecting to receive a List<DataGridViewRow> to work.

Now that Form2 is expecting the parameter I have for it… We can use it once we are done making our list of rows!

//Make an instance of Form2, passing it the list of Rows we just created
Form2 f2 = new Form2(listofrows);
f2.Show();//show the form

Having said all that. To accomplish your goal, at a high level, you want to

  1. iterate through the rows of your DataGridView
  2. accumulate the desired rows in a List or whatever you pick
  3. pass the List as parameter to Form2
  4. have Form2 perform whatever task you want with the incoming List of DataGridViewRow

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace DataGridViewRowsToForm2_46306622
{
    public partial class Form1 : Form
    {

        DataGridView dgv1 = new DataGridView();
        BindingList<dgventry> dgv1Data = new BindingList<dgventry>();
        Button btn = new Button();

        public Form1()
        {
            InitializeComponent();
            InitializeGrid();
            AddButton();
            AddData();
        }

        private void AddButton()
        {
            btn.Location = new Point(5, dgv1.Location.Y + dgv1.Height + 5);
            btn.Text = "Click to pass rows";
            btn.Click += Btn_Click;
            this.Controls.Add(btn);
        }

        private void Btn_Click(object sender, EventArgs e)
        {
            List<DataGridViewRow> listofrows = new List<DataGridViewRow>();
            foreach (DataGridViewRow item in dgv1.Rows)
            {
                DataGridViewRow r = (DataGridViewRow)item.Clone();
                for (int i = 0; i < item.Cells.Count; i++)
                {
                    r.Cells[i].Value = item.Cells[i].Value;
                }
                listofrows.Add(r);
            }
            Form2 f2 = new Form2(listofrows);
            f2.Show();
        }

        private void AddData()
        {
            for (int i = 0; i < 5; i++)
            {
                dgv1Data.Add(new dgventry
                {
                    col1 = "row " + i,
                    col2 = i.ToString(),
                    col3 = i.ToString()
                });
            }

        }

        private void InitializeGrid()
        {
            dgv1.Location = new Point(5, 5);
            dgv1.DataSource = dgv1Data;
            this.Controls.Add(dgv1);
        }
    }

    public class dgventry
    {
        public string col1 { get; set; }
        public string col2 { get; set; }
        public string col3 { get; set; }
    }
}

Form2.cs

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace DataGridViewRowsToForm2_46306622
{
    public partial class Form2 : Form
    {
        //Have a form constructor that accepts your GridViewRows as argument
        public Form2(List<DataGridViewRow> dgvc = null)
        {
            InitializeComponent();
            TextBox txtbx = new TextBox();
            txtbx.Location = new Point(5, 5);
            if (dgvc != null)
            {
                //iterate through the rows and do what you want with them
                foreach (DataGridViewRow item in dgvc)
                {
                    txtbx.Text += item.Cells[0].Value + "https://stackoverflow.com/";
                }
            }
            this.Controls.Add(txtbx);
        }
    }
}

Some people will suggest passing the DataSource instead. Sure, that will work… for as long as your DataSource matches the content of the DataGridView; It’s not necessarily the case all the time so pick your poison accordingly.

solved C# How to get all values of all rows in a dataGridView and pass it into another form