DatagridViewComboboxCell value changed in C# - c#

I have a DatagridviewCombobox Column and am creating DatagridviewCombobox Cells on each row and adding items to it.
When I change the value of any (combobox) cell, it throws an exception saying that Datagridviewcombobox cell value is not valid.
and the cell value becomes '1'.
I am working on the datagridview_currentcelldirtystatechange event, but haven't been able to make it work.
The code below is creating rows and filling combobox cells with a sequence numbers.
int _rowLimit =1;
for (int i = _rowLimit - 1; i < _rowLimit; i++)
{
datagridview.Rows.Add();
item = i + 1;
datagridview[myColumn, i].Value = _rowLimit;
DataGridViewComboBoxCell oCell = datagridview.CurrentRow.Cells[myColumn] as DataGridViewComboBoxCell;
oCell.Items.Add(item);
((DataGridViewComboBoxColumn)datagridview.Columns[myColumn]).Items.IndexOf(_rowLimit);
((DataGridViewComboBoxColumn)datagridview.Columns[myColumn]).Items.Insert(index, item);
}
And below is what i am doing in datagridview_currentcelldirtystatechange event:
for (int innerIndex = 0; innerIndex < datagridview.Rows.Count; innerIndex++)
{
long sequence = 3;
long oldSequence = 2;
long tempValue= Convert.ToInt64(datagridview.Rows[innerIndex].Cells[myColumn].Value);
if (tempValue <= sequence && tempValue> oldSequence)
{
datagridview.Rows[innerIndex].Cells[myColumn].Value = tempValue+ 1; // increment the sequence
// value here i am getting is correct , but it doesn't show in the DatagridviewCombobox cell where it gets changed of gridview and the mentioned exception is thrown.
}
Any help would be appreciated.
Thanks.

the error on selectedindexChange value of the combobox cells and the exception of DataGridviewComboboxcell value is not valid .. that automatically did change the selected vlue to '1'..
i fixed this issue by adding the DatagridviewComboBoxColumn property in the designer file.
this.columnName.ValueType = typeof(long);
typeof(long) // this is what what i wanted to show the value in the datagridviewcombobox column.
Issue has now resolved.
Thanks.

Related

How to update a cell value in datagridview using c#?

I want to update the value of cells in a datagridview using c#, the value gets updated but during the code execution it gives this error message.
Index was out of range, must be non negative and less than the size of the collection.parameter name: index
I have tried the column names as well as column index and also verified the row index, it actually updates the values but at each assignment statement it give the above error message and moves to next line. I am using this code,
foreach (DataGridViewRow row in SelectedItems.Rows)
{
if (Convert.ToInt32(row.Cells["SKU"].Value) == orderItem.ItemId)
{
decimal currentQuantity = Convert.ToDecimal(row.Cells["Quantity"].Value);
orderItem.Quantity = orderItem.Quantity + currentQuantity;
orderItem.Amount = orderItem.Quantity * orderItem.UnitPrice;
orderItem.Tax = orderItem.Tax * orderItem.Quantity;
orderItem.Discount = orderItem.Discount * orderItem.Quantity;
row.Cells["Quantity"].Value = orderItem.Quantity;
row.Cells["Amount"].Value = orderItem.Amount;
row.Cells["Tax"].Value = orderItem.Tax;
row.Cells["Discount"].Value = orderItem.Discount;
counter = 1;
CalculateTotal();
}
}

Labels value not changing based on condition

I have a gridview in winforms which displays bill details. There is a column named total. I created a label with a text "0". Then I used a for loop to get the sum of total column in labels text property.
decimal tot1 = 0;
for (int i = 0; i < dgv_SaleReport.RowCount - 1; i++)
{
tot1 += Convert.ToDecimal(dgv_SaleReport.Rows[i].Cells[7].Value);
}
label_Total1SaleReport.Text = tot1.ToString();
But this code is not working. I added same code in other menu items datagridview and it's working. Right now, I have a tabcontrol which has 4 tabs. In all these 4 tabs dgv the code is not working. Can't just figure it out.

Office Interop reading incorrect cell values

Trying to iterate through the rows and cells on an excel spreadsheet, deleting empty ones. I'm using the following routine to do so.
foreach(Range row in sheet.UsedRange.Rows)
{
for (int i = 0; i < row.Columns.Count; i++)
{
Range cell = row.Cells[1, i + 1];
if (cell.Value == null || String.IsNullOrEmpty(cell.Value.ToString()))
{
cell.Delete();
}
}
}
Which works fine for the first two rows. However, it then seems to go haywire.
The third row is completely empty. Yet as it iterates through the columns, when this loop gets to column "I", it reads a value there. The value is what's actually in row 4, column "J".
After that, it just gets worse, missing whole rows and reading incorrect values from the rows it does find.
I am baffled by this. Is there something obvious that I have missed?
Yes, you are missing something very obvious. You are deleting cells. After that operation, your calculation of which cell to pick doesn't work any more.
If you delete a cell, all other cells will move up. That causes your row.Cells[1, i + 1] to be incorrect. If you for example delete one cell in row 2, the value of the cell in the same column in row 3 will never get checked, since it is in row 2 then.
The direction of shift on deletion may also be a factor - you can control it by passing a parameter to the Delete function.
Simply recheck the same column when you delete one:
foreach (Range row in Globals.ThisAddIn.Application.ActiveWorkbook.ActiveSheet.UsedRange.Rows)
{
for (int i = 0; i < row.Columns.Count; i++)
{
Range cel = row.Cells[1, i + 1];
if (cel.Value == null || String.IsNullOrEmpty(cel.Value.ToString()))
{
// default shift is up
cel.Delete();
// to shift left use cel.Delete(XlDeleteShiftDirection.xlShiftToLeft);
i--; // this will do
}
}
}

Getting the ID of a GridView from a button Click contained within that gridview

I have a situation where I have Multiple GridViews on a page GridView1 - GridView4.
All these GridViews have TextBoxes in the cells, I would like to run a calculation function only on the Column of the TextBox that was Clicked and on that particular GridView.
Example: A user clicks on a TextBox in Column 2 of GridView3 and changes a number value, the OnTextChange event of that particular TextBox should fire to run a calculation and total all the numbers of GridView3 Col2 in a footer label.
I searched and all the other suggestions I found assume you have only 1 grid and that you know what preset Column the calculation is done at IE a prices column, But I don't know what Column info a user will edit in any of my 4 GridViews.
I gave up and resolved to just running the calculation code on the Entire GridView, not just the column edited, but to do this I need to Get the GridView.ID of the Gridview containing the TextBox. Extensive serches came up with how to get the ID of the sender Item but not the GridView.ID that contains the sender.
If anyone can help with either situation, please do so, I would really appreciate it.
As Per the conversations below, I have edited this post to include the Edited answer provided by Tim in the hopes that others may learn from this code:
//This is working code
protected void textBox_TextChanged(Object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
GridViewRow gvRow = (GridViewRow)txt.NamingContainer;
GridView Grid = (GridView)gvRow.NamingContainer;
// if you need the index of the column of the TextBox
int colIndex = 0;
for (int i = 0; i < gvRow.Cells.Count; i++)
{
if (gvRow.Cells[i] == txt.Parent)
{
colIndex = i;
Msg.Text = "Col: "+colIndex.ToString();
break;
}
}
int gridNum = 0;
switch (Grid.ID)
{
case "GridView1":
gridNum = 1;
break;
case "GridView2":
gridNum = 2;
break;
case "GridView3":
gridNum = 3;
break;
case "GridView4":
gridNum = 4;
break;
}
Label ColTotal = (Label)Grid.FooterRow.FindControl("G" + gridNum + "TotalPP" + colIndex);
double total = 0;
foreach (GridViewRow row in Grid.Rows)
{
TextBox tb = (TextBox)row.FindControl(txt.ID);
double d;
if (double.TryParse(tb.Text, out d))
total += d;
}
ColTotal.Text = total.ToString();
}
As you can see, according to the way the code is set up, the colIndex will help me find the footer label for each column and put it's total in.
You could let all TextBoxes handle the same TextChanged event and use this (untested) code:
protected void textBox_TextChanged(Object sender, EventArgs e)
{
TextBox txt = (TextBox) sender;
GridViewRow gvRow = (GridViewRow) txt.NamingContainer;
GridView gv = (GridView) gvRow.NamingContainer;
// if you need the index of the column of the TextBox
// as commented below you're using .NET 2.0
int colIndex;
for (int i = 0; i < gvRow.Cells.Count; i++)
{
if (gvRow.Cells[i] == txt.Parent)
{
colIndex = i;
break;
}
}
double total = 0;
foreach (GridViewRow row in gv.Rows)
{
TextBox tb = (TextBox)row.FindControl(txt.ID);
double d;
if (double.TryParse(tb.Text, out d))
total += d;
}
var tbFooter = (TextBox) gv.FooterRow.FindControl(txt.ID);
tbFooter.Text = total.ToString();
}
Of course assuming that all TextBoxes are in TemplateFields and the footer TextBox has the same ID. Remember to set AutoPostback to true if you want to postback immediately.
When TextChanged runs, sender is a reference to that textbox. You can use the parent property to find out what is the parent of that textbox. If you chain parents together (something like txt.Parent.Parent, you'll eventually find the GridViewRow, and GridView objects. Since you want to calculate the column, you'd have to find the cell that the control is in first, find the cell's index, then bubble up to the grid, loop through each row in that grid, and grab the values in the matching index. I hope you don't have paging enabled, because that will skew the numbers (since they aren't all present). Not an easy task, but possible.
From a performance perspective, you would get better performance with a client-side solution using JQuery or something else.

How to find the control of textbox inside the grid

I am using ASP.NET and I have one GridView that has a TextBox within an editTemplate, but I am not able to find the control; whenever I try to assign the value to TextBox of GridView I'm getting a NullReferenceException.
My code is as follows:
for (int i = 0; i < grdTransfer.Rows.Count; i++)
{
GridViewRow row = grdTransfer.Rows[i];
if (((CheckBox)row.FindControl("chkSelect")).Checked)
{
count = 1;
(row.FindControl("txtDestLocation") as TextBox).Text = txtLocation.Text;
}
}
Issue: NullReferenceException: object reference not set to the instance of an object.
This means I'm getting null whenever I try to assign the value of GridView TextBox from outside the TextBox at runtime.
What am I doing wrong?
A couple things.
WHere is the error happening, I see two likely places.
Does the grid have a header or footer? You aren't checking for either one?
Why aren't you doing this stuff as part of the GridView.RowDataBound event?
I think you are getting this exception on the very last loop.
Grid Row collection index start from Zero but the count will return the total number of row. So you should use count -1 while looping through...
for (int i = 0; i < grdTransfer.Rows.Count -1; i++)..
I would prefer using foreach(GridViewRow row in grdTransfer.Rows) instead.

Categories

Resources