I have added rows into gridview. There are 20 columns in gridview. How can i do a colspan-like feature in gridview which could show me 2-3 rows under 2-3 columns and remaining as a colspan.
Basically i wish to implement colspan in gridview on the rows of the gridview.
hence my present gv is like ;
Col 1 Col 2 Col 3 Col 4 ...... Col 20
Cell1 Cell2 Cell3 Cell 4 ...... Cell 20 (For Rows # 1)
I wish to have something like
Col 1 Col 2 Col 3 Col 4 ...... Col 20
Cell1 Cell2 ...... Cell 20 (For Rows # 1)
Let me know for any query.
Thanks
You need to handle the OnRowCreated event of the GridView as follows:
protected void grid_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.Cells[2].ColumnSpan = 2;
//now make up for the colspan from cell2
e.Row.Cells.RemoveAt(4);
}
}
Your markup should be something like this:
<asp:GridView runat="server" ID="grid" OnRowCreated="grid_RowCreated" >
On the above example, I populated the grid with this:
DataTable dt = new DataTable();
for (int i = 0; i < 5; i++)
{
dt.Columns.Add("Col " + i);
}
for (int i = 0; i < 10; i++)
{
DataRow r = dt.NewRow();
r.ItemArray=new object[]{"row "+i,"row "+i,"row "+i,"row "+i,"row "+i};
dt.Rows.Add(r);
}
grid.DataSource = dt;
grid.DataBind();
And it produces this:
I just realized that you wanted to have the ROWS (not necessarily the header) to have certain colspan, in which case you can do:
protected void grid_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[2].ColumnSpan = 2;
//now make up for the colspan from cell2
e.Row.Cells.RemoveAt(4);
}
}
And it will produce:
BoundField and TemplateField tags has the property ItemStyle-Width="22%" as you can see you can set it for each column with a percentage to be responsive
Related
Table1 Fig.
Name | Marks
Pritam | 80
Aruna | 85
Uttaran | 90
Total | 255
DataTable dtStudentInfo = table1;
dataGridView1.DataSource = dtStudentInfo;
After Clicking on the column header name datagridview sort in ascending order of students' name. But I want the Total row always stays at the last of list.
I want to know if there is any way by which I can remove the last row from the list which will be sorted. If this is not possible then suggest any way by which i can get the result. NOTE: I don't want any external button to sort the list.
I've solved the problem by the following way:
DataGridViewRow dgRowTotalCount;
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
{
dgRowTotalCount = (DataGridViewRow)dataGridView1.Rows[((DataGridView)sender).Rows.Count - 1].Clone();
for (Int32 index = 0; index < ((DataGridView)sender).Rows[((DataGridView)sender).Rows.Count - 1].Cells.Count; index++)
{
dgRowTotalCount.Cells[index].Value = ((DataGridView)sender).Rows[((DataGridView)sender).Rows.Count - 1].Cells[index].Value;
}
((DataGridView)sender).Rows.RemoveAt(((DataGridView)sender).Rows.Count - 1);
}
}
private void dataGridView1_Sorted(object sender, EventArgs e)
{
DataTable dtDGVCopy = new DataTable();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
dtDGVCopy.Columns.Add(col.Name);
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dRow = dtDGVCopy.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dtDGVCopy.Rows.Add(dRow);
}
dtDGVCopy.Rows.Add();
for (Int32 i = 0; i < dgRowTotalCount.Cells.Count - 1; i++)
{
dtDGVCopy.Rows[dtDGVCopy.Rows.Count-1][i] = dgRowTotalCount.Cells[i].Value;
}
dataGridView1.DataSource = null;
dataGridView1.DataSource = dtDGVCopy;
}
But its not smooth as it was before. If there is any way by which i can make it's performance as it was before that would be great.
I know this is an old question, but here is a solution I've come up with. Use the SortCompare event on the grid to override the sorting for a specific row:
private void dgvData_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
if (dgvData.Rows[e.RowIndex1].Cells[0].Value.ToString() == "Total" ||
dgvData.Rows[e.RowIndex2].Cells[0].Value.ToString() == "Total")
{
if (dgvData.SortOrder == SortOrder.Ascending)
{
e.SortResult = -1;
}
else
{
e.SortResult = 1;
}
e.Handled = true;
}
}
Now any row that has "Total" in the first column will always sort to the end of the grid.
(If you allow columns to be reordered then you'll need to figure out how to check the correct column)
I have a gridview with first columns is same as headers i.e. same value with autogeneratecolumns as true, what i need to do in RowDatabound if HeaderText Equals to Intersect of the first Column text, Change the color to Yellow. Please see the attached image of the Desireed Gridview Output.
GridViewDesiredOutput
HTML
<asp:GridView ID="GvSamples" OnRowDataBound="GvSamples_RowDataBound" runat="server" AutoGenerateColumns="True">
C#
public void BindSamplesGrid()
{
DataTable _dt = new DataTable();
_dt = BL.GetSample(_conn);
GvSamples.DataSource = _dt;
GvSamples.DataBind();
}
protected void GvSamples_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
for (int i = 0; i < e.Row.Cells.Count; i++)
{
if (e.Row.Cells[i].Text == e.Row.Cells[i].Text)
e.Row.Cells[i].Text = e.Row.Cells[i].Text.Replace("_", " ");
}
}
}
I am using asp.net C# Gridview.
Thank you
There are a couple of issues with your code. First of all you can only access the header row in DataControlRowType.Header, so coloring the cells as desired must be done in DataControlRowType.DataRow.
Next you are evaluating exactly the same value, so it will always be true: e.Row.Cells[i].Text == e.Row.Cells[i].Text, although this does not seem to do much except replace a _, which has nothing to do with getting the cell color to be yellow.
The below snippet does what you need. It gets the current row number and colors the correct cell yellow.
protected void GvSamples_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//get the current row number
int rowIndex = e.Row.RowIndex;
//check if the rownumber does not exceed the column count
if (rowIndex < e.Row.Cells.Count - 1)
{
//make the cell yellow
e.Row.Cells[rowIndex + 1].BackColor = Color.Yellow;
}
}
}
I'm in a situation were need to achieve multiple colspan and two header row using ASP.Net gridview.
Something like below
+----------+--------------------------------+--------------------------------+
|Name |English |Math |
| |----------+----------+----------+----------+----------+----------+
| |1st Term |2nd Term |3rd Term |1st Term |2nd Term |3rd Term |
+----------+----------+----------+----------+----------+----------+----------+
|Adam |50 |60 |70 |55 |65 |75 |
+----------+----------+----------+----------+----------+----------+----------+
|Smith |52 |62 |72 |57 |68 |70 |
+----------+----------+----------+----------+----------+----------+----------+
Is it possible to do it?
Edit : Number of rows and / or columns or even sub-headers of a header is not fixed.
Access to the RowSpan and ColumnSpan for a grid view is done through the Cells property.
To access the header cells:
//Replace ColumnSpan with RowSpan if needed (and if you can get multiple header rows)
Gridview1.HeaderRow.Cells[CELL_INDEX].ColumnSpan = 2; //Need to know the cell index
To access the cells of a normal row:
//Replace ColumnSpan with RowSpan if needed
Gridview1.Rows[ROW_INDEX].Cells[CELL_INDEX].ColumnSpan = 2; //Need to know the row index and the cell index in that row
The multiple header row might be a bit more tricky. I've never done it, but the guy here seemed to have a good answer: How to add Header and Subheader in Gridview
It can be done, but it takes a bit of trial and error to get the design you want. Use the GridView OnRowDataBound event. It would be easier to do this after the GridView is build, especially for RowSpan.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
int spanColumn_1_start = 1;
int spanColumn_1_length = 3;
//apply colspan
e.Row.Cells[spanColumn_1_start].ColumnSpan = 3;
//remove the spanned cells
for (int i = 1; i < spanColumn_1_length; i++)
{
e.Row.Cells.RemoveAt(spanColumn_1_start + 1);
}
//note that the startindex of the 2nd colspan is set after removing cells for 1st colspan
int spanColumn_2_start = 2;
int spanColumn_2_length = 3;
//apply colspan
e.Row.Cells[spanColumn_2_start].ColumnSpan = 3;
//remove the spanned cells
for (int i = 1; i < spanColumn_2_length; i++)
{
e.Row.Cells.RemoveAt(spanColumn_2_start + 1);
}
}
else if (e.Row.RowType == DataControlRowType.DataRow)
{
int rowIndex = e.Row.DataItemIndex;
//to make a rowspan you have to work backwards since the next row does not exist yet
if (rowIndex == 1)
{
GridView1.Rows[rowIndex - 1].Cells[0].RowSpan = 2;
e.Row.Cells.RemoveAt(0);
}
//span 4 rows in column 3 starting at row 6
if (rowIndex == 9)
{
int rowSpan = 4;
int columnIndex = 3;
//apply rowspan
GridView1.Rows[rowIndex - rowSpan].Cells[columnIndex].RowSpan = rowSpan;
//remove the spanned rows
for (int i = 1; i < rowSpan; i++)
{
GridView1.Rows[rowIndex - (rowSpan - i)].Cells.RemoveAt(columnIndex);
}
}
}
}
The above snippet will give the following result.
UPDATE
To add an extra header row you need to use the OnRowCreated event of the GridView.
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
//cast the sender back to a gridview
GridView gv = sender as GridView;
//check if the row is the header row
if (e.Row.RowType == DataControlRowType.Header)
{
//create a new row
GridViewRow extraHeader = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
extraHeader.BackColor = Color.Green;
//loop all the columns and create a new cell for each
for (int i = 0; i < gv.Columns.Count; i++)
{
TableCell cell = new TableCell();
cell.Text = "ExtraHeader " + i;
//add the cell to the new header row
extraHeader.Cells.Add(cell);
}
//add the new row to the gridview
gv.Controls[0].Controls.AddAt(0, extraHeader);
}
}
I am currently have a gridview with no row, only header. I have an ASP control textbox with a OnTextChange event. So everytime I input into a number into the textbox, my gridview will generate number of rows based on it. And inside the row, will have a dropdownlist
For instance, in my textbox, I type number 2, 2 rows will be generated in the gridview.
I am currently using ASP.NET
Textbox:
[ 2 ]
GridView:
----------------------------------------------------
| S/N | | |
----------------------------------------------------
| 1 | [dropdownlist] | [dropdownlist] |
|--------------------------------------------------|
| 2 | [dropdownlist] | [dropdownlist] |
--------------------------------------------------
Here is a snippet to get you started. Inside your GridView you can use <TemplateField> to create the layout you want. After that you might want to look into the OnRowDataBound event to fill the DropDownLists.
protected void Button1_Click(object sender, EventArgs e)
{
int rowCount = 0;
//get the number from the textbox and try to convert to int
try
{
rowCount = Convert.ToInt32(TextBox1.Text);
}
catch
{
}
//set the new rowcount as a viewstate so it can be used after a postback
ViewState["rowCount"] = rowCount;
//start the function to fill the grid
fillGrid();
}
private void fillGrid()
{
int rowCount = 0;
//get the current row count from the viewstate
if (ViewState["rowCount"] != null)
{
rowCount = Convert.ToInt32(ViewState["rowCount"]);
}
//create a new DataTable with three columns.
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Created", typeof(DateTime));
//loop to add the row to the table
for (int i = 0; i < rowCount; i++)
{
table.Rows.Add(0, "Name_" + i.ToString(), DateTime.Now.AddMinutes(i));
}
//bind the table to the grid
GridView1.DataSource = table;
GridView1.DataBind();
}
This code inserts a row under the first row that i choose to edit but when i edit the second row now new row appears can someone tell me or show me how to correct this. I've tried doing e.Row.RowInex + 1 and i get no rows. but if i do e.Row.RowInex + 2 i get a new row for the first but not the second.
protected void PageSettings_DataBound(object sender, GridViewRowEventArgs e)
{
if ((e.Row.RowState & DataControlRowState.Edit) > 0))
{
GridViewRow row = new GridViewRow(e.Row.RowIndex + 2, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
row.Cells.AddRange(CreateCells());
Table table = e.Row.Parent as Table;
table.Rows.AddAt(e.Row.RowIndex + 2, row);
}
}
private TableCell[] CreateCells()
{
TableCell[] cells = new TableCell[2];
TableCell cell;
cell = new TableCell();
cell.ColumnSpan = 2;
cells[0] = cell;
cell = new TableCell();
cell.ColumnSpan = 4;
cells[1] = cell;
return cells;
}
Solved for any one who has this trouble
((e.Row.RowState & DataControlRowState.Edit) > 0)
For a response to your title question: 'How do test for an alternating row in DataBound':
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.RowState == DataControlRowState.Alternate)
{
// alternate rows
}
}
}