I'm using a ASP.NET GridView and now I want to define the colspan automatically.
I had th VB code and I converted it to C#. My code is currently looking like that, but the .Cells and .Rows aren't working. Does anyone know what's wrong. Am I not allowed to use these?
+ I found the right namespace: System.Windows.Forms
but then I also need to use
System.Windows.Forms.DataGridViewCellCollection; but where do I put it?
protected void grdvCamp_DataBound1(object sender, EventArgs e)
{
for (int rowIndex = grdvCamp.Rows.Count - 2; rowIndex >= 0; rowIndex += -1)
{
GridViewRow gvRow = grdvCamp.Rows(rowIndex);
GridViewRow gvPreviousRow = grdvCamp.Rows(rowIndex + 1);
for (int cellCount = 0; cellCount <= gvRow.Cells.Count - 9; cellCount++)
{
if (gvRow.Cells(cellCount).Text == gvPreviousRow.Cells(cellCount).Text)
{
if (gvPreviousRow.Cells(cellCount).RowSpan < 2)
{
gvRow.Cells(cellCount).RowSpan = 2;
}
else
{
gvRow.Cells(cellCount).RowSpan = gvPreviousRow.Cells(cellCount).RowSpan + 1;
}
gvPreviousRow.Cells(cellCount).Visible = false;
}
}
}
}
I think the right syntax should be
.Rows[rowIndex]
.Cells[cellCount]
instead of
.Rows(rowIndex)
.Cells(cellCount)
since both returns a collection. As far as I know, () syntax uses in vb.net but [] uses in C#. When you write grdvCamp.Rows(rowIndex) in C#, it looks Rows as a method of grdvCamp, not a collection.
For more information;
GridView.Rows property
TableRows.Cells property
Related
I have a function that sets column values for all rows:
The code that sets this:
//Update the engineers for all rows
Btn_ValidateClick_ItemClick(object sender,ItemClickEventArgs e)
{
UpdateTotalTime(gridView);
}
private void UpdateEngineers(DevExpress.XtraGrid.Views.Base.ColumnView View)
{
//Column name that need to be updated (set)
DevExpress.XtraGrid.Columns.GridColumn col = View.Columns.ColumnByFieldName("Engineers");
try
{
int dataRowCount = View.DataRowCount;
for (int i = 0; i < dataRowCount; i++)
{
GridView detail = (GridView)gridView.GetDetailView(i, 0);
string language = gridView.GetRowCellValue(i, "Language").ToString();
for (int y = 0; y < gridView.GetDetailView(i, 0).RowCount; y++)
{
//Add all values found in a detail column to an arraylist
values.Add(detail.GetRowCellValue(y, "EngineerInitials").ToString());
}
if (values.Count >0 )
object t = //string join ...
View.SetRowCellValue(i, col, t);
}
else
{
object t = "No engineers"
View.SetRowCellValue(i, col, t);
}
}
}
}
}
The problem is that now, I want it only to set it for the rows that are selected.
I tried using the .GetSelectedRows()-function and adding the rows to an ArrayList, but this doesn't allow customability really:
private void UpdateTotalTime(DevExpress.XtraGrid.Views.Base.ColumnView View)
{
ArrayList selectedRows = new ArrayList();
for (int i = 0; i < gridView.SelectedRowsCount; i++)
{
if (gridView.GetSelectedRows()[i] >= 0)
selectedRows.Add(gridView.GetDataRow(gridView.GetSelectedRows()[i]));
}
try
{
int count = View.GetSelectedRows().Count();
for (int i = 0; i < selectedRows.Count; i++)
{
//This gets the first row of the count, not the first selected row
GridView detail = (GridView)gridView.GetDetailView(i,0);
}
}
If I select the 3 bottom rows, the first 3 get updated. Why is this?
You are adding all the selected rows to your selectedRows ArrayList. But after that, you are not using it for anything.
I guess what you want (I've never used devexpress controls) is using those selectedrows RowHandle to pass it to the GetDetailView method. According to the GetSelectedRows documentation, the method returns the int handles of the selected rows, so your code should look like this:
First, you must save the DataRow handles, not the DataRow itself, so you must change in your code this line:
selectedRows.Add(gridView.GetDataRow(gridView.GetSelectedRows()[i]));
into this:
selectedRows.Add(gridView.GetSelectedRows()[i]);
And then, change your loop into this:
for (int i = 0; i < selectedRows.Count; i++)
{
int rowHandle = (int)selectedRows[i];
GridView detail = (GridView)gridView.GetDetailView(rowHandle,0);
}
In fact, you could do everything in just one loop:
private void UpdateTotalTime(DevExpress.XtraGrid.Views.Base.ColumnView View)
{
for (int i = 0; i < gridView.SelectedRowsCount; i++)
{
int rowHandle = gridView.GetSelectedRows()[i];
GridView detail = (GridView)gridView.GetDetailView(rowHandle,0);
}
}
Currently I try to use Repeater WebControl in order to display a table that list out all possible component. Below is my table;
Right now I try to merged cells in Group Code and Group Description column that have the same value. Below is my merging cell code, noted that the code is in class;
public void repeaterRowSpan(string repeaterID, string columnID)
{
var pageHandler = HttpContext.Current.CurrentHandler;
Control ctrl = ((Page)pageHandler).Master.FindControl("ContentPlaceHolder3").FindControl(repeaterID);
Repeater repeaterName = (Repeater)ctrl;
for (int i = repeaterName.Items.Count - 1; i > 0; i--)
{
HtmlTableCell oCell_previous = (HtmlTableCell)repeaterName.Items[i - 1].FindControl(columnID);
HtmlTableCell oCell = (HtmlTableCell)repeaterName.Items[i].FindControl(columnID);
oCell.RowSpan = (oCell.RowSpan == -1) ? 1 : oCell.RowSpan;
oCell_previous.RowSpan = (oCell_previous.RowSpan == -1) ? 1 : oCell_previous.RowSpan;
if (oCell.InnerText == oCell_previous.InnerText)
{
oCell.InnerText = "";
oCell_previous.RowSpan += oCell.RowSpan;
}
}
}
Somehow the code manage to delete the same value in the column but maintain the rowspan. When I debugged, the oCell_previous.RowSpan return '2' so the code itself working fine. Below is the result of merging;
How can I modified my code in such way it will merged the cell?
In your opinion, between Repeater and GridView which is most suitable to show data in table form in this project? In my understanding, Repeater is most suitable since it faster than GridView. GridView is only suitable if you have edit function to go with your table.
This can be implemented using the OnDataBound event. The OnDataBound event of the GridView is executed after the GridView is populated with the records. Executed a loop in reverse over the GridView Rows and then the common Cells are identified and merged into single cell.
Below sample code merges the first & second columns (assuming that there are redundant values by comparing the above row(s)),
Feel free to leave a comment if you need more info.
protected void OnDataBound(object sender, EventArgs e)
{
for (int i = GridView1.Rows.Count - 1; i > 0; i--)
{
GridViewRow row = GridView1.Rows[i];
GridViewRow previousRow = GridView1.Rows[i - 1];
for (int j = 0; j < row.Cells.Count; j++)
{
if (row.Cells[j].Text == previousRow.Cells[j].Text)
{
if (previousRow.Cells[j].RowSpan == 0)
{
if (row.Cells[j].RowSpan == 0)
{
previousRow.Cells[j].RowSpan += 2;
}
else
{
previousRow.Cells[j].RowSpan = row.Cells[j].RowSpan + 1;
}
row.Cells[j].Visible = false;
}
}
}
}
}
I want to pass DataGridviewRow as a ref where i am assigning some value to its cells but i am unable to do this
foreach(DataGridViewRow dgr in dgvMarksEntryByClassWise.Rows)
{
RowValueSet(ref dgr);
}
Here it is giving Compile time Error because dgr is an foreach iteration variable
Also i tried to do it with for loop
for (int i = 0; i < dgvMarksEntryByClassWise.Rows.Count; i++)
{
RowValueSet(ref dgvMarksEntryByClassWise.Rows[i]);
}
But here also it is giving Compile time error:
A property,indexer or dynamic member acces cannot passed as an out reference
I referd this question asked on above errors but did't Found any appropriate solution of my problem
foreach iteration variable
A property,indexer or dynamic member acces cannot passed as an out reference
Please Suggest me how to Do this
Update Code
void RowValueSet(ref DataGridViewRow dgr)
{
dgr.Cells["StudentZero"].Value = ss.Where(w => w.MarksheetMarks == "0").Count();
if (ss.Count() != 0)
dgr.Cells["StudentISEmpty"].Value = Convert.ToInt16(lblTotlatStudent1.Text) - ss.Count();
else
dgr.Cells["StudentISEmpty"].Value = 0;
dgr.Cells["StudentEntry"].Value = ss.Count();
}
you cannot assign an iterated, enumerated item using a "foreach" or even a "for".
i got around that once, using that piece of code :
List<DataGridViewRow> lstDgr = new List<DataGridViewRow>();
foreach(DataGridViewRow dgr in dgvMarksEntryByClassWise.Rows)
{
DataGridViewRow dgrTemp = dgr;
RowValueSet(ref dgrTemp);
lstDgr.Add(dgrTemp);
}
dgvMarksEntryByClassWise.Rows.Clear();
dgvMarksEntryByClassWise.Rows.AddRange(lstDgr); //Not sure about the AddRange, try the Add method instead
Hope this helps
As stated in the comments above, you do not need to pass DataGridViewRow by reference. Remove ref from the parameter.
void RowValueSet(DataGridViewRow dgr)
{
dgr.Cells["StudentZero"].Value = ss.Where(w => w.MarksheetMarks == "0").Count();
if (ss.Count() != 0)
dgr.Cells["StudentISEmpty"].Value = Convert.ToInt16(lblTotlatStudent1.Text) - ss.Count();
else
dgr.Cells["StudentISEmpty"].Value = 0;
dgr.Cells["StudentEntry"].Value = ss.Count();
}
If the values in the grid do not appear to be updating, it's for another reason. Do you re-bind the grid when you need to refresh the display?
How about this ?
for (int i = 0; i < dgvMarksEntryByClassWise.Rows.Count; i++)
{
var myRow = dgvMarksEntryByClassWise.Rows[i];
RowValueSet(ref myRow);
}
I agree with the comments about not passing the row using ref. It is a reference type. You generally only use that keyword with value types (such as int, etc).
I've had problems with the DataGridView not updating after changing cell values and often have needed to call dataGridView1.Invalidate(); It depends how things are hooked up. If you use data-binding with a class that inherits from INotifyPropertyChanged then it always seems to work, but if you just change cell values I have noticed the odd time that it would not update.
Here is an example that works. Create a new app, add an empty DataGridView onto the form and replace the code with the following. This proves that you do not need to use ref.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Column1" });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Column2" });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Column3" });
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Column4" });
for (int i = 0; i <= 4; i++)
{
dataGridView1.Rows.Add();
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
RowValueSet(row);
}
}
private void RowValueSet(DataGridViewRow row)
{
row.Cells["Column1"].Value = "1";
row.Cells["Column2"].Value = "2";
row.Cells["Column3"].Value = "3";
row.Cells["Column4"].Value = "4";
}
}
I imagine that your problem lies elsewhere
I am trying to get a calculated column in DataGridView, at first I thought it was simple but now I have been struggling for an hour.
The code below works fine when editing columns:
private void ReceiptDataGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
DataGridViewRow RecieptRow = RecieptDataGrid.Rows[e.RowIndex];
RecieptRow.Cells[4].Value = double.Parse(RecieptRow.Cells[2].Value.ToString()) * double.Parse(RecieptRow.Cells[3].Value.ToString());
}
But I am struggling to make the column take its value automatically when new rows are added.
I get a NullReferenceException
exception when I use the same code.
I have tried a for loop and got the same error
private void RecieptDataGrid_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
for (int i = 0; i < e.RowCount; i++)
{
DataGridViewRow RecieptRow = RecieptDataGrid.Rows[e.RowIndex + i];
RecieptRow.Cells[4].Value = double.Parse(RecieptRow.Cells[2].Value.ToString()) * double.Parse(RecieptRow.Cells[3].Value.ToString());
}
}
I Realize that it sees the cells at nulls about is there a workaround to this?
Help please.
Thank You.
you could check if your RecieotRow is a new row (with empty values) by using the IsNewRow property:
for (int i = 0; i < e.RowCount; i++)
{
DataGridViewRow RecieptRow = RecieptDataGrid.Rows[e.RowIndex + i];
if (RecieptRow.IsNewRow) continue;
RecieptRow.Cells[4].Value = double.Parse(RecieptRow.Cells[2].Value.ToString()) * double.Parse(RecieptRow.Cells[3].Value.ToString());
}
I found the problem, it was reading the row default values as nulls.
I replaced the default properties by adding the default value to the string that adds data to the DataGrid.
I want to sort the data in datagridview by numbers, and I want to display the specific cell of last row in a textbox. How can I do that?
my code : (EDITED)
if (dataGridView1.Rows.Count > 0)
{
int nRowIndex = dataGridView1.Rows.Count - 1;
dataGridView1.Rows[nRowIndex].Selected = true;
textBox2.Text = dataGridView1.Rows[nRowIndex].Cells[2].Value.ToString() ; << exception occur
And i get this NullReferenceException.
How to solve this?
PS: I have 3 columns there, I need to get the 3rd columns of the last row.
You are getting exeption because you are trying to get the fourth cell (dataGridView1.Rows[nRowIndex].Cells[3]) and you have, as you said, only 3 cells(columns). Just change your code to:
textBox2.Text = dataGridView1.Rows[nRowIndex].Cells[2].Value.ToString()
textBox2.Text = dataGridView1.Rows[nRowIndex].Cells[dataGridView1.Columns.Count -1].Value.ToString() ;
Based on your last comment, I have changed your code a bit:
if (dataGridView1.Rows.Count > 0)
{
int nRowIndex = dataGridView1.Rows.Count - 1;
dataGridView1.Rows[nRowIndex].Selected = true;
if(dataGridView1.Rows[nRowIndex].Cells[2].Value != null)
textBox2.Text = dataGridView1.Rows[nRowIndex].Cells[2].Value.ToString() ; }
In page_load ()
write :-> gvJobCard.PageIndex = Int32.MaxValue;
protected void gvJobCard_RowDataBound(object sender,GridViewRowEventArgs e)
{
gvJobCard.PageIndex = gvJobCard.PageCount - 1; //It works for DESC order in gvJOBCARD
}