I want to merge table but i don't know how. I have already tried many times but still can't get the right solution. Right now my gridview is like this :
Data 1 | Data 1 | Data 1 | Data 1
Data 1 | Data 1 | Data 1 | Data 1
Data 2 | Data 2 | Data 2 | Data 2
Data 2 | Data 2 | Data 2 | Data 2
And I want the gridview to be like this :
Data 1 | Data 1 | Data 1 | Data 1
| Data 1 | Data 1 |
Data 2 | Data 2 | Data 2 | Data 2
| Data 2 | Data 2 |
How to merge cells with equal values in a GridView
this will help you
The code that merges the cells is very short:
public class GridDecorator
{
public static void MergeRows(GridView gridView)
{
for (int rowIndex = gridView.Rows.Count - 2; rowIndex >= 0; rowIndex--)
{
GridViewRow row = gridView.Rows[rowIndex];
GridViewRow previousRow = gridView.Rows[rowIndex + 1];
for (int i = 0; i < row.Cells.Count; i++)
{
if (row.Cells[i].Text == previousRow.Cells[i].Text)
{
row.Cells[i].RowSpan = previousRow.Cells[i].RowSpan < 2 ? 2 :
previousRow.Cells[i].RowSpan + 1;
previousRow.Cells[i].Visible = false;
}
}
}
}
}
The last action is to add an OnPreRender event handler for the GridView:
protected void gridView_PreRender(object sender, EventArgs e)
{
GridDecorator.MergeRows(gridView);
}
Related
I've seen this article http://asp.net-informations.com/gridview/newrow.htm and this post http://forums.asp.net/p/1534978/3725419.aspx#3725419 and I've done it for have that separator row collapsible with jquery and it's working great in display mode. The problems occuring when try to do something else with gridview, because there's a weird behaviour.. I've add a simple button that have just to set a radiobutton that's in every gridview row (except in the new added GroupHeaders rows). Then if I have added two new row he is skipping setting the last two rows in the GridView..
public void AddNewRow(object sender, GridViewRowEventArgs e)
{
GridView GridView1 = (GridView)sender;
GridViewRow NewTotalRow = new GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
TableCell HeaderCell = new TableCell();
HeaderCell.Attributes.Add("onclick", "collapsible('" + rowgroup + "')");
NewTotalRow.Cells.Add(HeaderCell);
TableCell HeaderCellIndex = new TableCell();
int indexCorrente = e.Row.RowIndex + index;
HeaderCellIndex.Text = indexCorrente.ToString();
NewTotalRow.Cells.Add(HeaderCellIndex);
GridView1.Controls[0].Controls.Add(NewTotalRow);
}
protected void gdDettaglio_RowCreated(object sender, GridViewRowEventArgs e)
{
bool newRow = false;
if ((DataBinder.Eval(e.Row.DataItem, "Stato") != null))
{
if (statoCorrente != Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "Stato").ToString()))
newRow = true;
}
if (newRow)
{
AddNewRow(sender, e);
}
}
Printing the row index (just to check it) next to each row I'm displaying this situation (with two GroupHeader rows added):
(The index are as they are printing them in gdDettaglio_RowCreated for GroupHeadrs rows and on gdDettaglio_OnDataBound for the other rows)
-----------------------------------------
| HEADER |
|---------------------------------------|
-----------------------------------------
| Gruppo 1 | index -1 |
|---------------------------------------|
| grp1 | x | blablabla | | index 0 |
| grp1 | y | blablabla | | index 1 |
| grp1 | z | blablabla | | index 2 |
| grp1 | x | blablabla | | index 3 |
| grp1 | x | blablabla | | index 4 |
|---------------------------------------|
| Gruppo 2 | index -1 |
|---------------------------------------|
| grp2 | x | blablabla | | index 5 |
| grp2 | y | blablabla | | index 6 |
| grp2 | z | blablabla | | index 7 |
| grp2 | z | blablabla | | index 8 |
| grp2 | z | blablabla | | index 9 |
| grp2 | z | blablabla | | index 10 |
-----------------------------------------
in the button code I've just:
foreach (GridViewRow riga in gdDettaglio.Rows)
{
if (riga.RowType == DataControlRowType.DataRow)
{
RadioButtonList rad = (RadioButtonList)riga.FindControl("rad");
rad.SelectedValue = "True";
}
}
UPDATE:
Doing the same thing on jquery work, it affects all the row:
function accettaTutte() {
$("#<%=gdDettaglio.ClientID%> tr:has(td)").each(function () {
var items = $(this).find("[id$='radDaPa'] input:radio'");
for (var i = 0; i < items.length; i++) {
if (items[i].value == 'True') {
if (!(items[i].checked)) {
items[i].checked = true;
}
break;
}
}
});
return false;
}
But I still need to do a foreach on that gridview, to update db, some idea on what could try to do? On every row I've also a "single row save" ImageButton, but clicking on it on the last two rows it's not firing the RowCommand event... It's like the two added GroupHeader rows are pushing out the last two data rows, no matter about the index.. If I click the ImageButton on the row with displayed (using Text='<%#Container.DataItemIndex%>') rowIndex 2, in the rowCommand it become rowIndex 3, but it modified the right row, the one I've clicked.. If i do the same on row 7, it become 9.. But if forced it to get value on rowIndex 11, U'm getting ArgumentOutOfRangeException, because Rows.Count It's still 11..
OK, now I am adding to the list that is GridView DataSource as many empty elements as are the GroupHeaders rows, so GridView.Rows.Count is enough to get all the rows..
I'm Working on a c# projet (webform).
Is it possible to Hide the name of the column when I Bind my DataTable to the Gridview ?
This is my DataTable:
¤----------¤----------¤----------¤
| Column 1 | Column 2 | Column 3 |
¤----------¤----------¤----------¤
| Data 1 | Data 1 | Data 1 |
¤----------¤----------¤----------¤
| Data 4 | Data 5 | Data 6 |
¤----------¤----------¤----------¤
and I would like to reach this in my GridView
¤----------¤----------¤----------¤
| Data 1 | Data 1 | Data 1 |
¤----------¤----------¤----------¤
| Data 4 | Data 5 | Data 6 |
¤----------¤----------¤----------¤
Is it possible and How could I do it please ?
EDIT:
In The First Row,I have many datas which are the same. How Could I join my cells in C# on my DataTable please?
¤----------¤----------¤----------¤----------¤----------¤----------¤
| Data 1 | Data 2 |
¤----------¤----------¤----------¤----------¤----------¤----------¤
| Data 4 | Data 5 | Data 6 | Data 7 | Data 8 | Data 9 |
¤----------¤----------¤----------¤----------¤----------¤----------¤
I would Like to reach this if possible
Have you tried setting the GridView's ColumnHeadersVisible property to False?
EDIT:
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "Column1", "Column2" ...);
in web form
<asp:GridView runat="server" HeaderStyle-CssClass="hide">
</asp:GridView>
in css
.hide { display: none; }
DataRow dr = dt.Rows[0];
dr.Delete();
dt.AcceptChanges();
After that bind your datatable to your grid.
Edit
protected void OnDataBound(object sender, EventArgs e)
{
GridViewRow row = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal);
TableHeaderCell cell = new TableHeaderCell();
cell.Text = "Your text1";
cell.ColumnSpan = 3;
row.Controls.Add(cell);
cell = new TableHeaderCell();
cell.ColumnSpan = 3;
cell.Text = "Your text2";
row.Controls.Add(cell);
GridView1.HeaderRow.Parent.Controls.AddAt(0, row);
}
I have some data in a grid that currently displays like this:
------------------
|Hd1| Value |
------------------
|A | A1 |
------------------
|A | A2 |
------------------
|A | A3 |
------------------
|A | A4 |
------------------
|B | B1 |
------------------
|B | B2 |
------------------
|B | B3 |
------------------
|B | B4 |
------------------
|B | B5 |
------------------
|C | C1 |
------------------
|C | C2 |
------------------
I want to make it look like this:
|Hd | Value |
------------------
|A | A1 |
----------
| | A2 |
----------
| | A3 |
----------
| | A4 |
------------------
|B | B1 |
----------
| | B2 |
----------
| | B3 |
----------
| | B4 |
----------
| | B5 |
------------------
|C | C1 |
----------
| | C2 |
------------------
Is there any way that I can merge these cells?
I have tried in many ways also google but did not find any suitable way.
If it is possible showing this data another way without using datagridview but the result is the way I have showed, that will also solve my problem.
You must first find a duplicate values
Need to two methods:
bool IsTheSameCellValue(int column, int row)
{
DataGridViewCell cell1 = dataGridView1[column, row];
DataGridViewCell cell2 = dataGridView1[column, row - 1];
if (cell1.Value == null || cell2.Value == null)
{
return false;
}
return cell1.Value.ToString() == cell2.Value.ToString();
}
in the event, cellpainting:
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None;
if (e.RowIndex < 1 || e.ColumnIndex < 0)
return;
if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex))
{
e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None;
}
else
{
e.AdvancedBorderStyle.Top = dataGridView1.AdvancedCellBorderStyle.Top;
}
}
now in cell formatting:
if (e.RowIndex == 0)
return;
if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex))
{
e.Value = "";
e.FormattingApplied = true;
}
and in form_load:
dataGridView1.AutoGenerateColumns = false;
The DataGridView control has no related properties or methods to merge cells, but you can accomplish the same using custom painting. You can use DataGridView.CellPainting event or override the Paint method.
Plus you will need to override the DataGridView.CellClick, CellEnter, CellFormatting and other methods as well in order to give your DataGridView a full featured functionality. For eg on cell click, the entire merged cell (or group of cells that constitute a merged cell) will have to be custom painted.
You can find some sample code here:
http://social.msdn.microsoft.com/forums/en-US/vbinterop/thread/5b659cbd-7d29-4da4-8b38-5d427c3762e2
http://forums.codeguru.com/showthread.php?415930-DataGridView-Merging-Cells
http://www.codeproject.com/Questions/152113/How-can-i-merge-DataGridView-Rows-Cells-with-Equal
There are some good responses on asp.net but in winforms and for this example(merging same data in columns) it is not defined.
You can use color.transparent to hide the same values in datagridview.
even by this code, same rows do not deleted and can be good for matematical calculations.
even you can define which columns to merge by your desire sort.
In this way if end of "A" was "A4" and also start of "B" was "A4" those would not be merge. which is Often more desired. (If you do not want this, better use other responses)
MergeGridviewCells(DGV,new int[] {0,1});//For example if you want to merge first columns data/then 3th column and then second column you can use new int[] {0,2,1}
private void MergeGridviewCells(DataGridView DGV, int[] idx)
{
DataGridViewRow Prev = null;
foreach (DataGridViewRow item in DGV.Rows)
{
if (Prev != null)
{
string firstCellText = string.Empty;
string secondCellText = string.Empty;
foreach (int i in idx)
{
DataGridViewCell firstCell = Prev.Cells[i];
DataGridViewCell secondCell = item.Cells[i];
firstCellText = (firstCell != null && firstCell.Value != null ? firstCell.Value.ToString() : string.Empty);
secondCellText = (secondCell != null && secondCell.Value != null ? secondCell.Value.ToString() : string.Empty);
if (firstCellText == secondCellText)
{
secondCell.Style.ForeColor = Color.Transparent;
}
else
{
Prev = item;
break;
}
}
}
else
{
Prev = item;
}
}
}
Preview:
I spent a long time looking for this as my boss didn't want to buy any off-the-shelf components. This should be submitted into the .NET code: datagridvewtextboxcell-with-span-behaviour It just works and is soo simple to use. Works with VB/C# .NET 4.5 to 6. Spans rows and columns including headers.
DataGridView.Columns.Add(new DataGridViewTextBoxColumnEx());
DataGridViewTextBoxCellEx dataGridViewCell = (DataGridViewTextBoxCellEx)DataGridView[colIdx, rowIdx];
dataGridViewCell.ColSpan = 2;
dataGridViewCell.RowSpan = 6;
I have the data below in a datatable this is example data. I would like get the occurrence of 12,13 in the datatable as normally there would be 10-20 million row in the datatable.
Customer | quantity | Product | Code
1 | 3 | Product | 12
2 | 4 | Product | 13
3 | 1 | Product | 12
4 | 6 | Product | 13
how about simple for each loop
private int getCount(int yourSearchDigit)
{
int counter = 0;
foreach (DataRow dr in youDataTable.Rows)
{
if (Convert.ToInt32(dr["Code"]) == yourSearchDigit)
counter++;
}
return counter;
}
You can use Linq-To-DataTable:
int[] allowedCodes = new []{ 12, 13 };
var rows = table.AsEnumerable()
.Where(r => allowedCodes.Contains(r.Field<int>("Code")));
However, if you have 10-20 million row in the datatable you should consider to do the filtering in the database itself.
If you want to know the number they occur:
int count = table.AsEnumerable()
.Count(r => allowedCodes.Contains(r.Field<int>("Code")));
There is a gridview which includes 6 columns. I bound the data to some columns. For example, 3 and 5 th columns have data.
I want to show There is 2 data in first columns if there is 3 data in separate columns I want to write 3 in the first column.
Column1 | Column2 | Column3 | Column4 | Column5 | Column6
2 | | stack | | overflow |
4 | sta | ck | over | flow |
1 | | | | | stcvrflw
How can I do it?
I populate the grid
e.Row.Cells[i].Text = html;
and html variable includes < table>.... some values come from db.
After you populate the grid:
for (int i = 0; i < gv.Rows.Count; i++)
{
valueCount=0;
for (int j = 1; j < gv.Columns.Count; j++)
{
if (gv.Rows[i].Cells[j].ToString()!="")
valueCount++;
}
gv.Rows[i].Cells[0].Text =valueCount.ToString();
}