Getting System.FormatException while trying to cast - c#

I have a function to duplicate a row in DataGridView which looks like this:
private void dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = sender as DataGridView;
// If button clicked
if (e.ColumnIndex == 0)
{
// Get values what you want to use
var value1 = dgv.Rows[e.RowIndex].Cells[1].Value;
var value2 = dgv.Rows[e.RowIndex].Cells[2].Value;
// Insert a new row behind the click one
dgv.Rows.Insert(e.RowIndex + 1);
// Set the previously stored values
dgv.Rows[e.RowIndex + 1].Cells[1].Value = value1;
dgv.Rows[e.RowIndex + 1].Cells[2].Value = value2;
}
}
Now i wanted to write a function for one specific cell to increase + 1 with every click. For example: if in Cell[2] the value is 1, with the next added row the value should count up to 2, 3 and so on. I´ve tried to operate with + but i´ve got a error message that the operator cannot be applied to type of object. So i´ve tried to cast the specific cell like this:
var value2 = Convert.ToInt32(dgv.Rows[e.RowIndex].Cells[2].Value);
But now i get a SystemFormatException: Input string was not in a correct format.
Any ideas?
Many thanks in advance!

Allow only numeric values as below
private void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
// Textbox columns
if (dgv.CurrentCell.ColumnIndex == 2)
{
TextBox tb = e.Control as TextBox;
if (tb != null)
{
tb.KeyPress += TextBox_KeyPress;
}
}
}
private void TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
// Only numeric characters allowed
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}

Related

Add tooltip to specific column on Data Grid View

I have a Data Grid View like:
if (this.dgv.Rows.Count < 1)
{
this.dgv.DataSource = null;
this.dgv.DataBindings.Clear();
if (this.dgv.Columns.Count == 0) this.dgv.ColumnCount = 15;
this.dgv.ColumnHeadersVisible = true;
this.dgv.Columns[4].Name = "Added By";
this.dgv.Columns[5].Name = "AddedByFullName";
}
as you can see I have column 4 called Added By
this.dgv.Columns[4].Name = "Added By";
and column 5 called AddedByFullName
this.dgv.Columns[5].Name = "AddedByFullName";
I want to know how can I use AddedByFullName column as a tooltip for Added By column then I will just remove AddedByFullName column , is that possible? Regards
You can do this using the CellMouseEnter or CellToolTipTextNeeded event for the DataGridView. Hide the column you want to use as the source, then replace the control name in the sample to match your DataGridView.
private void dgv_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if ((e.ColumnIndex == dgv.Columns["Added By"].Index)
&& (e.RowIndex > -1))
{
dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].ToolTipText = dgv.Rows[e.RowIndex].Cells[dgv.Columns["AddedByFullName"].Index].Value.ToString();
}
}
Using CellMouseEnter event can be a posibility to achieve this but it also can be done with CellFormatting event as Microsoft REFERENCE
private void dgJobNotes_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if ((e.ColumnIndex == this.dgJobNotes.Columns["Added By"].Index)
&& e.Value != null)
{
dgJobNotes.Rows[e.RowIndex].Cells[e.ColumnIndex].ToolTipText = dgJobNotes.Rows[e.RowIndex].Cells[5].Value.ToString();
}
The DataGridViewColumn class has a ToolTipText property. If you set it on the column, you will get a tool tip for the column header. If you want a tool tip to show up on every cell, you can implement a CellFormatting event handler, pull out the right cell (from the column) and set the cell's ToolTipText property. Something like:
private const int InterestingColumnNumber = 5;
private const string InterestingColumnToolTipText = "This Space For Rent";
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
var senderGridView = sender as DataGridView;
if (senderGridView != null)
{
if (e.ColumnIndex == InterestingColumnNumber)
{
var cell = senderGridView.Rows[e.RowIndex].Cells[InterestingColumnNumber];
cell.ToolTipText = InterestingColumnToolTipText;
}
}
}
There is a CellToolTipTextNeeded event which is created specifically for setting tooltip text. You don't need to use use CellFormatting or CellMouseEnter. If you are going to show text of column 5 as tooltip of column 4, you can write:
private void g_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
{
if (e.ColumnIndex == 4 && e.RowIndex >= 0)
{
e.ToolTipText = $"{dataGridView1[5, e.RowIndex].Value}";
}
}

get values fron current column of DataGridView on keypress or keydown event C#

Problem:I want to get inserted characters(AccountID) in cell of datagridview, so that i can get respective username from database.
i had stuck in problem that on keypress event of datagridview, it is not getting recently insert char. For example,if user name is 'John Snow' its ID=JN. When I write 'J' in datagridview cell, and get value on keypress, it gets "". when I write further as 'JN', it gets 'J'. similarly, on 'JNE' , it gets 'JN' , so then i get JohnSnow from Database. In short, It get previous value not recently inserted.
I have Implement it as,
public DebitCredit()
{
InitializeComponent();
this.KeyPreview = true;
this.KeyPress += new KeyPressEventHandler(Control_KeyPress);
}
private void Control_KeyPress(object sender, KeyPressEventArgs e)
{
//Get the column and row position of the selected cell
int column = DGV_DEBIT_CREDIT.CurrentCellAddress.X;
int row = DGV_DEBIT_CREDIT.CurrentCellAddress.Y;
DataTable result=null;
if (column == 0)
{
string test = DGV_DEBIT_CREDIT[column, row].EditedFormattedValue.ToString();
result = getpro.SearchAccountByID(test);
if (result != null)
{
if (result.Rows.Count > 0)
{
DGV_DEBIT_CREDIT[column, row].Value = result.Rows[0][0].ToString();
DGV_DEBIT_CREDIT[column + 1, row].Value = result.Rows[0][1].ToString();
}
else
{
DGV_DEBIT_CREDIT[column, row].Value = "".ToString();
DGV_DEBIT_CREDIT[column + 1, row].Value = "".ToString();
}
}
}
}
First handle EditingControlShowing event of DataGridView as shown below. For the current control getting edited in the datagridview column, handle keyUp event as shown below.
Then you can see the expected result.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyUp += new KeyEventHandler(Control_KeyUp);
}
private void Control_KeyUp(object sender, KeyEventArgs e)
{
//YOUR LOGIC
// string test = dataGridView1[0, 0].EditedFormattedValue.ToString();
}

How to make the new added unbound column value auto number become static?

First I make an unbound column in GridView (using DevExpress):
public void buttonl_Click(object sender, EventArgs e)
{
//GridColumn clmn = gridaaa.Columns["code"];
if (gridaaa.Columns.ColumnByFieldName("idx") != null)
{
gridaaa.Columns.ColumnByFieldName("idx").Dispose();
}
GridColunn unbColumn2 = gridaaa.Columns.AddField("idx");
unbColumn2.VisibleIndex = gridaaa.Columns.Count;
unbColumn2.UnboundType = DevExpress.Data.UnboundColumnType.Integer;
//// Disable editing.
unbColumn2.OptionsColunn.AllowEdit = false;
// gridaaa.Columns.ColumnByFieldName("idx").Dispose();
}
In the gridView1_CustomUnboundColumnData event I am using this code
private void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
{
if (e.Column.FieldName == "idx")
{
e.Value = e.ListSourceRowIndex;
}
}
for the output or result was:
The question is how to make the index or idx column value become static when I click sorting in any column header. As you can see when I click genre header the value follow with code or index in database, I want to make it like autonumber from 0 whenever I keep click column header of genre or anything:
You can use ColumnView.GetRowHandle method to get the handle of current row which is always reflects to the position of row in GridView from up to down.
Here is example:
private void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
{
if (e.Column.FieldName == "idx")
e.Value = gridView1.GetRowHandle(e.ListSourceRowIndex);
}

Event located immediately after DataSource Update from ActiveEditor in Grid

What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid. I need to run this calculation After the value in one of the dependent cells is changed, but only if the value was a Valid entry. The EditValueChanged, Validating, and Validated events of the editor/repository all occur before the data is posted back into the datasource. I am wondering if there is any event I can hook into that will allow me to fire this calculation after the data has been post back into the datasource, but before control is returned to the user.
Sample Code
//calculation functions
private void SetCalcROP(MyObjectt Row)
{
//rop = m/hr
TimeSpan ts = Row.ToTime - Row.FromTime;
double diffDepth = Row.EndDepth - Row.StartDepth;
if (ts.TotalHours > 0)//donot divide by 0
Row.ROP = diffDepth / ts.TotalHours;
else
Row.ROP = 0;
}
private void SetCalcDeltaP(MyObject Row)
{
Row.DeltaPress = Row.SPPOnBtm - Row.SPPOffBtm;
}
//events
private void repNumberInput_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colSPPOff) || vwDDJournal.FocusedColumn.Equals(colSPPOn))
SetCalcDeltaP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colStartDepth) || vwDDJournal.FocusedColumn.Equals(colEndDepth))
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repTimeEdit_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (string.IsNullOrEmpty(TE.Text))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column may not be blank");
return;
}
else
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repNumberInput_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (!string.IsNullOrEmpty(TE.Text))
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repTimeEdit_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (vwDDJournal.FocusedColumn.Equals(colToTime))
{//dont bother to check from time
//TIME TRAVEL CHECK!!!!
DateTime FromTime = Convert.ToDateTime(vwDDJournal.GetRowCellValue(vwDDJournal.FocusedRowHandle, colFromTime));
TimeEdit te = sender as TimeEdit;
DateTime ToTime = Convert.ToDateTime(te.EditValue);
if (ToTime < FromTime)
{//TIME TRAVEL
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "To Time must be greater than From Time");
return;
}
}
}
the problem is that everywhere I call this from, and whether I use vwDDJournal.GetRowCellValue(...) or vwDDJournal.GetFocusedRow() as MyObject, I still get the old edit value.
Requirements
I have to have the input validated before running the calculation.
I have to run the calculation immediately after making the change.
... What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid.
The best way to accomplish this task is using Unbound Columns feature.
The following example demonstrates how to implement this feature by handling the ColumnView.CustomUnboundColumnData event:
// Provides data for the Total column.
void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e) {
if (e.Column.FieldName == "Total" && e.IsGetData) e.Value =
getTotalValue(e.ListSourceRowIndex);
}
// Returns the total amount for a specific row.
decimal getTotalValue(int listSourceRowIndex) {
DataRow row = nwindDataSet.Tables["Order Details"].Rows[listSourceRowIndex];
decimal unitPrice = Convert.ToDecimal(row["UnitPrice"]);
decimal quantity = Convert.ToDecimal(row["Quantity"]);
decimal discount = Convert.ToDecimal(row["Discount"]);
return unitPrice * quantity * (1 - discount);
}
Original example: How to: Add an Unbound Column Storing Arbitrary Data
You can also implement calculated value for unbound column using expressions:
GridColumn columnTotal = new GridColumn();
columnTotal.FieldName = "Total";
columnTotal.Caption = "Total";
columnTotal.UnboundType = DevExpress.Data.UnboundColumnType.Decimal;
columnTotal.UnboundExpression = "[Quantity] * [UnitPrice] * (1 - [Discount])";
gridView1.Columns.Add(columnTotal);
How about CustomCellValue?
After posting back to the data source refresh the data.
It's called whenever data is updated or view is changed.

Change behaviour of editable column of DataGridView

I have a DataGridView, in which I have a column. This column is not readonly, and the purpose of it is to be able to write text in every cell. When I select a empty cell and start typing, it works as expected. However, when there already is text in a cell, and I start typing, all the existing text is removed. How can I prevent this?
Example:
The cell already contains "ABC". When I type D, I want the cell to contain "ABCD", but it only contains "D".
Assume dg as your datagridview. Try assigning the following event handler EditingControlShowing, CellEnter, CellLeave to your datagridview. And you should be feeling good now.
string str = string.Empty;
int i = 0;
private void dg_CellEnter(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
str = dgv[e.ColumnIndex, e.RowIndex].Value.ToString();
}
void dg_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
TextBox tb = (TextBox)e.Control;
tb.TextChanged += new EventHandler(tb_TextChanged);
}
void tb_TextChanged(object sender, EventArgs e)
{
if (i == 0)
{
i++;
DataGridViewTextBoxEditingControl dgv = (DataGridViewTextBoxEditingControl)sender;
string curVal = dgv.Text;
dgv.Text = str + curVal;
dgv.SelectionStart = dgv.Text.Length;
}
dg.EditingControlShowing -= new DataGridViewEditingControlShowingEventHandler(dg_EditingControlShowing);
dg.CellEnter -= new DataGridViewCellEventHandler(dg_CellEnter);
}
private void dg_CellLeave(object sender, DataGridViewCellEventArgs e)
{
i = 0;
}
Hope it helps.

Categories