1

I have been trying to do the said above things with this code:

protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        //Populating a table from the database
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connect"].ToString());
        con.Open();
        SqlDataAdapter da = new SqlDataAdapter("Select * from tbluser", con);
        DataTable dt = new DataTable();
        da.Fill(dt);
        DataTable finaldt = new DataTable();
        foreach (DataColumn column in dt.Columns)
        {
            if (column.ColumnName == "user_name")
            {
                finaldt.Columns.Add("Username", typeof(string));
            }else if (column.ColumnName == "first_name")
            {
                finaldt.Columns.Add("First Name", typeof(string));
            }else if (column.ColumnName == "last_name")
            {
                finaldt.Columns.Add("Last Name", typeof(string));
            }else if (column.ColumnName == "email")
            {
                finaldt.Columns.Add("E-mail", typeof(string));
            }else if (column.ColumnName == "grade")
            {
                finaldt.Columns.Add("Grade", typeof(string));
            }
        }
        finaldt.Columns.Add("Edit", typeof(Button));
        foreach (DataRow row in dt.Rows)
        {
            Button removalButton = new Button();
            removalButton.Text = "Remove";
            removalButton.ID = "remove_" + row["user_name"];
            removalButton.Click += new EventHandler(remove_student);
            finaldt.Rows.Add(row["user_name"], row["first_name"], row["last_name"], row["email"], row["grade"], removalButton);
        }

        GridView1.DataSource = finaldt;
        GridView1.DataBind();

Near the bottom where I am adding rows to "finaldt", I am not sure this logic is completely valid for trying to set up a column for buttons with the

finaldt.Columns.Add("Edit", typeof(Button));

line. Should I be doing something differently here?

Aryan Firouzian
  • 1,940
  • 5
  • 27
  • 41
Sohee
  • 23
  • 5

2 Answers2

1

You can´t add a button to a DataTable. You will have to add the button to the DataGridViewRow whenever you finished loading the DataTable.

DataGridViewButtonColumn buttonColumn = new DataGridViewButtonColumn();
buttonColumn.Name = "YourColumn";
buttonColumn.Text = "YourText";

if (YourDataGrid.Columns["YourColumn"] == null)
{
    YourDataGrid.Columns.Insert(4, buttonColumn); //here you have to put the columnIndex
}

Then you will have to add the handler:

YourDataGrid.CellClick += dataGridViewButton_CellClick;

And then do something with it:

private void dataGridViewButton_CellClick(object sender, DataGridViewCellEventArgs e)
{
    //YOUR CODE IN HERE
}
NicoRiff
  • 4,803
  • 3
  • 25
  • 54
  • Just one issue I have with a method like this, is that there is nowhere to add a unique ID to each button. I need a unique ID because each button is supposed to function as a removal of that row from the database. Unless each button in the button column has some sort of index that I can access when it is clicked and it goes into the event handler? – Sohee Oct 30 '17 at 20:00
  • you can add a non visible column with the ID of your database... and whenever you click you can get the value of that column – NicoRiff Oct 30 '17 at 20:02
1

I hope I am not missing something; however, I am not sure if I follow what you mean by…

”…dynamically add a button with a unique identity in DataGridView for each row”

If there is a column of buttons in a grid, about the only thing that would “uniquely” identify which button was clicked, is the ROW it is in. Using your example to “Remove” the row when the button is clicked is straightforward… however; this is an event that can be done in the GRID… not necessarily in the button click event… which will not be available since the button is in the grid.

I suggest you simply add the button column, then wire up the grids CellClick event and check to see if the button column was clicked. If the button column were clicked then we would simply need to get the row index of the clicked button. With the row index, you would know which row to remove.

This appears straightforward, however, as your example uses a DataTable as a data source for the grid, then an extra step may be necessary. The same principle would apply using another “type” of data source. In this case the data source is a DataTable.

Using a data source for the grid implies that the data source itself and what the grid displays MAY not necessarily be the same. Example: If you sort the grid by clicking on a column header the grid will obligingly sort that column and display the sort in the grid. However, chances are high that the data source DataTable does not necessarily reflect this sort, therefore when the user clicks on the remove button, the row index retuned from the grid will reflect the “grids” row index, not necessarily the DataTables row index.

One possible solution is to use the grids DataBoundItem property. This will return an object that can be cast to a DataRowView object. The DataRowView object can be used as a parameter to the DataTables IndexOf property to find the DataTables row index. Thus giving the row index we need to remove from the DataTable. The commented code below does this if you need the row index. Instead of getting the row index the DataTable.Rows.Remove property is used to remove the returned DataRowView.Row object instead. I hope this helps.

Below is an example of what is described above.

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  if (e.RowIndex >= 0 && e.ColumnIndex >= 0 && (!dataGridView1.Rows[e.RowIndex].IsNewRow)) { 
    if (dataGridView1.Columns[e.ColumnIndex].Name == "Remove") {
      DataRowView dataRowView = (DataRowView)dataGridView1.Rows[e.RowIndex].DataBoundItem;
      if (dataRowView != null) {
        //int rowIndex = gridTable.Rows.IndexOf(dataRowView.Row);
        //gridTable.Rows.RemoveAt(rowIndex);
        gridTable.Rows.Remove(dataRowView.Row);
      }
    }
  }
}


DataTable gridTable;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  gridTable = GetTable();
  dataGridView1.DataSource = gridTable;
  AddButtonColumnToDGV();
  FillTable(gridTable);
}

private void AddButtonColumnToDGV() {
  DataGridViewButtonColumn buttonCol = new DataGridViewButtonColumn {
    Name = "Remove",
    Text = "Remove",
    UseColumnTextForButtonValue = true
  };
  dataGridView1.Columns.Add(buttonCol);
}

private DataTable GetTable() {
  DataTable dt = new DataTable();
  dt.Columns.Add("User Name", typeof(string));
  dt.Columns.Add("First Name", typeof(string));
  dt.Columns.Add("Last Name", typeof(string));
  dt.Columns.Add("Grade", typeof(string));
  return dt;
}

private void FillTable(DataTable dt) {
  for (int i = 0; i < 10; i++) {
    dt.Rows.Add("Name" + i, "FName" + i, "LNameR" + i, "GradeR" + i);
  }
}
JohnG
  • 9,259
  • 2
  • 20
  • 29
  • Just one question, is datagridview the same thing as gridview? Because it will not let me add a column of type "DataGridViewButtonColumn" to "GridView1". – Sohee Oct 31 '17 at 16:23
  • A `DataGridView` and a `GridView` are TWO different things. I am not 100% sure, however I believe a `GridView` may be used in an ASP.net web environment. The main point is that in either case you will need to de-couple the button column from the data source. – JohnG Oct 31 '17 at 18:56
  • Your code appears to be trying to add the button to the data source itself…this may or may not work depending on your data source. However, it does not make sense to add the button column to the data source itself since it has nothing to do with the data source. In addition, if you add a button to the data source, you may need to remove it if you try to write the data source back to your database. – JohnG Oct 31 '17 at 18:56
  • In my example the button column is simply used as a separate function of the grid… namely to remove the row the button is in when it is clicked. I hope this makes sense. – JohnG Oct 31 '17 at 18:56