DataGridView EditingControlShowing doesn't fire - c#

After a long time of search on the web for my problem, i ask the question...
I have a DataGridView whith DataGridViewComboBoxColumn in the 2 first columns.
When I change manually the value of the 1st column of the last row, I add a new blank row after this last row if needed.
When I change manually the value of the second column, I change the type of the next columns (Text or Combo) and fill the DataGridViewComboBoxCell.
These 2 points work perfectly with the EditingControlShowing event whitch fires other events. I use this event whitch is the only one returns a ComboBox as e.Control.
My problem is when I want to programmatically fill the values of col 1 & col 2, the EditingControlShowing event doesn't fire as it should.
I've tried with BeginEdit property, with EditMode=EditProgrammatically property, with no more success.
Here is a part of my code (this not the project but a part of a sample, and I can send more if necessary) :
private void btnFill_Click(object sender, EventArgs e)
{
List<string[]> sFilters = new List<string[]>();
string[] filter1 = { "col3", "NOT IN" };
string[] filter2 = { "col5", "BETWEEN" };
sFilters.Add(filter1);
sFilters.Add(filter2);
iRow = -1;
foreach (var sVar in sFilters)
{
iRow++;
try
{
iCol = 0;
dataGridView1.CurrentCell = dataGridView1.Rows[iRow].Cells[iCol];
dataGridView1.BeginEdit(true);
dataGridView1.CurrentCell.Value = sVar[0];
//dataGridView1.EndEdit();
}
catch (Exception Ex)
{
MessageBox.Show("btnFill_Click - iCol=0 - iRow=" + iRow.ToString() + " :\n\n" + Ex.Message);
}
try
{
iCol = 1;
dataGridView1.CurrentCell = dataGridView1.Rows[iRow].Cells[iCol];
//dataGridView1.BeginEdit(true);
dataGridView1.CurrentCell.Value = sVar[1];
//dataGridView1.EndEdit();
}
catch (Exception Ex)
{
MessageBox.Show("btnFill_Click - iCol=1 - iRow=" + iRow.ToString() + " :\n\n" + Ex.Message);
}
}
}
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
iCol = ((DataGridView)(sender)).CurrentCell.ColumnIndex;
iRow = ((DataGridView)(sender)).CurrentCell.RowIndex;
if (iCol == 0)
{
try
{
// Déclenchement d'un évènement quand 'cboVar' change
ComboBox combo = e.Control as ComboBox;
if (combo != null)
{
// first remove event handler to keep from attaching multiple
combo.SelectedIndexChanged -= new EventHandler(dataGridView1_cboVar_SelectedIndexChanged);
// now attach the event handler
combo.SelectedIndexChanged += new EventHandler(dataGridView1_cboVar_SelectedIndexChanged);
}
((DataGridView)sender).ClearSelection();
}
catch (Exception Ex)
{
MessageBox.Show("EditingControlShowing() - Col0 :\n\n" + Ex.Message);
}
}
else if (iCol == 1)
{
try
{
ComboBox combo = e.Control as ComboBox;
if (combo != null)
{
// first remove event handler to keep from attaching multiple
combo.SelectedIndexChanged -= new EventHandler(dataGridView1_cboOpe_SelectedIndexChanged);
// now attach the event handler
combo.SelectedIndexChanged += new EventHandler(dataGridView1_cboOpe_SelectedIndexChanged);
}
}
catch (Exception Ex)
{
MessageBox.Show("EditingControlShowing() - Col1 :\n\n" + Ex.Message);
}
}
}
private void dataGridView1_cboVar_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
comboVar = sender as ComboBox;
if (iCol == 0)
{
if (comboVar.SelectedIndex > 0)
{
if (iRow == dataGridView1.RowCount - 1)
dataGridView1.Rows.Add();
}
comboVar.SelectedIndexChanged -= new EventHandler(dataGridView1_cboVar_SelectedIndexChanged);
}
}
catch (Exception Ex)
{
MessageBox.Show("dataGridView1_cboVar_SelectedIndexChanged() :\n\n" + Ex.Message);
}
}
I hope that I am clear enougth...
Thanks a lot for the help, and sorry for my poor English...
Herve

Related

Clicking datagrid buttom programmatically

What I'm trying to do is: I have a datagrid which is populated. The last column is a button and i have a time countdown which then presses a button and populates the datagrid. I then want to loop the datagrid and press the button programmatically (like a .PerformClick()) action.
CellContentClick
private void dgView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (toolStrip.Text != "You are successfully logged in ...") {
Helpers.returnMessage("You are not logged in ... aborting ...");
return;
}
// once found we execute: reportBackFound() and update the database
//Helpers.returnMessage("Clicked programatically!");
var senderGrid = (DataGridView)sender;
string rowId = senderGrid.Rows[e.RowIndex].Cells[0].Value.ToString();
string rowNm = senderGrid.Rows[e.RowIndex].Cells[1].Value.ToString();
string rowUi = senderGrid.Rows[e.RowIndex].Cells[2].Value.ToString();
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0)
{
try {
XmlDocument doc = new XmlDocument();
doc.Load("https://www.thesite.com/api.php?getApiData=1");
XmlNodeList _nodeList = doc.SelectNodes("/api/apiData");
foreach (XmlNode _node in _nodeList)
{
if (rowNm == _node["apiName"].InnerText)
{
// here we do an http webrequest to the url: _node["apiUrl"].InnerText we look for: zd_show.cgi? in the html
// if we find this it's a success.
var success = _useratorRequester.getReportsPage(_node["apiUrl"].InnerText);
if (success.Contains("zd_show.cgi?"))
{
reportBackFound(int.Parse(rowId), int.Parse(_node["apiId"].InnerText));
updateTheLog(int.Parse(rowId), _node["apiName"].InnerText, int.Parse(rowUi), "success");
} else {
// just update the reports log ...
updateTheLog(int.Parse(rowId), _node["apiName"].InnerText, int.Parse(rowUi), "in-progress");
}
if (chkBoxDebug.Checked)
{
File.AppendAllText("Debug\\userator-social.html", success, Encoding.GetEncoding("windows-1251"));
}
} else {
// there is no project in the userator system ...
}
}
} catch (Exception ex) {
Helpers.returnMessage("API TASKS:\n\n" + ex.ToString());
}
}
}
Timer
private void timerCountDown_Tick(object sender, EventArgs e)
{
counter--;
if (counter == 0)
{
timerCountDown.Stop();
btnParseTasks.PerformClick();
foreach (DataGridViewRow row in dgView.Rows) {
if (row.Cells["col4"].Value.ToString() == "Action") {
// perform click event
dgView_CellContentClick(dgView, new DataGridViewCellEventArgs(0, 0));
}
}
counter = 5;
}
lblCountDown.Text = counter.ToString() + " seconds until next check.";
}
I know I need to launch the event handler:
dgView_CellContentClick(dgView, new DataGridViewCellEventArgs(0, 0));
this line is not correct, I'm not sure what to pass in for DataGridViewCellEventArgs.

In WPF is it possible to force an update to a datagrid on keyup event?

I have a datagrid with multiple rows and columns. One of the columns is a numeric value. The user can edit this column to change the value in this cell/column. This column is totaled and the number is displayed under the datagrid. I want to have this number update as soon as the user enter a number. On the KeyUp event I call a routine that unloads the datagrid to a datatable and then I read through the column and count the value in this column. However when the datagrid is unloaded the original value is still the cell value. Is there away to force the update before I unload the datagsrid?
Here is my code:
private void dtGrid_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
int intKeyValue;
try
{
if (dtGrid.CurrentColumn.DisplayIndex == 1)
{
if (e.Key == Key.Enter || e.Key == Key.Return || e.Key == Key.Tab || e.Key == Key.NumLock)
{
SendKeys.SendWait("{TAB}");
}
else
{
intKeyValue = GetNumericValue(e.Key.ToString());
if (e.Key == Key.LeftShift || e.Key == Key.RightShift || e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
{
e.Handled = true;
}
else
{
if (intKeyValue < 0 || intKeyValue > 9)
{
System.Windows.MessageBox.Show("Only numbers are allowed.");
e.Handled = true;
}
}
}
}
}
catch (Exception ex)
{
string strMsg = "Error occured in Start Row key event. ";
System.Windows.MessageBox.Show(strMsg + ex.Message);
//throw new NotImplementedException();
}
}
private void dtGrid_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
e.Handled = true;
UpdateRowSize();
}
private void UpdateRowSize()
{
DataTable dtFieldSizes = new DataTable();
int intRowSize;
string strTotalRowSizeData;
string[] strRowSizeInfo;
try
{
intRowSize = 0;
dtGrid.UpdateLayout();
dtFieldSizes = ((DataView)dtGrid.ItemsSource).ToTable();
for (int intRowCnt = 0; intRowCnt < dtFieldSizes.Rows.Count; intRowCnt++)
{
intRowSize += Convert.ToInt16(dtFieldSizes.Rows[intRowCnt]["Size"]);
}
strTotalRowSizeData = lblRowSize.Content.ToString();
strRowSizeInfo = strTotalRowSizeData.Split(':');
if (Convert.ToInt16(strRowSizeInfo[1]) != intRowSize)
{
lblRowSize.Content = strRowSizeInfo[0] + ": " + Convert.ToString(intRowSize);
}
}
catch (Exception ex)
{
string strMsg;
strMsg = "RefreshRowSize, error '" + ex.Message + "' has occurred.";
System.Windows.MessageBox.Show(strMsg);
}
}
You can handle AutoGeneratingColumn and set UpdateSourceTrigger of the column Binding to be PropertyChanged. Assuming that this is your DataTable:
var tab = new DataTable();
tab.Columns.Add("a", typeof(double));
tab.Rows.Add(tab.NewRow());
tab.Rows[0][0] = 45;
And this is your DataGrid and its ItemsSource:
DataGrid gr = new DataGrid();
gr.ItemsSource = tab.AsDataView();
Handle:
gr.AutoGeneratingColumn += Gr_AutoGeneratingColumn;
in which
private void Gr_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
DataGridTextColumn col = e.Column as DataGridTextColumn;
if (col != null)
{
Binding binding = new Binding("[" + col.Header.ToString() + "]");
binding.Mode = BindingMode.TwoWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
col.Binding = binding;
}
}
In this setting, the value of the DataGrid updates, while you are typing in the cell.
Instead of updating the value datagrid keydown/up event, you can try with DataGridCell' keyup/keydown event

DataGridView RowFilter double and CurrentCultureInfo issues

I currently have a DGV populated by a DB Table with a column storing a double value (DB Collation: SQL_Latin1_General_CP1_CI_AS). Whenever I trigger a rowfilter by textbox_changetext event I get a format exception, code as follows:
if (textBox4.Text != "" && textBox4.Text.Replace("*", "").Length > 0)
{
filtertext += string.Format("[Esp (mm)]= {0} AND ", Convert.ToDouble(textBox4.Text));
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
try
{
(dataGridView4.DataSource as DataTable).DefaultView.RowFilter = filtertext;
state = State.Pending;
dataGridView4.Refresh();
label13.Text = "Total de registros: " + dataGridView4.Rows.GetRowCount(DataGridViewElementStates.Visible);
}
catch (Exception err)
{
claMisc.MsgBox(err.ToString());
}
}
My CurrentCultureInfo is based on a NumberDecimalSeparator="," and DGV seems to be loaded under this format, however "Convert.ToDouble" returns "." as DecimalSeparator. How can I get around that?
Solved. The filter was triggering a EnterCell event with empty datagridview. The solution was this if:
public void event(sender, eventargs)
{
if (dataGridView.Rows.Count>0 && dataGridView.SelectedCells.Count>0 && dataGridView.SelectedCells[0].RowIndex<dataGridView.Rows.Count) continue...
}

Change Focus of dataGridView cell in C#

I have the dataGridview in c# for Purchase order entry. I want to change the cell Focus from ItemId to NoofQty when I press Enter key after selecting ItemId. Then again press Enter key go to next row ItemId.
Which dataGridview event is suitable for this? Could you please anyone help me..
I have tried as far as I can as below
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
if(e.ColumnIndex==0)// ItemId
{
dataGridView1.Rows[e.RowIndex].Cells[4].Selected= true;
dataGridView1.Rows[e.RowIndex].Cells[4].Value="1";
//I want to edit this cell value
}
else if (e.ColumnIndex == 4)// ItemId
{
//goto next row and cell is ItemId
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Try this:
DataGridViewRow selectedRow = myGridView.Rows[rowToSelect];
selectedRow.Selected = true;
selectedRow.Cells[columnToSelect].Selected = true;
OR
myGridView.CurrentCell = myGridView.Rows[index].Cells[4];
myGridView.BeginEdit(true);
private void Form1_Load(object sender, EventArgs e)
{
DataGridViewComboBoxColumn cmb = (DataGridViewComboBoxColumn)dataGridView1.Columns[0];
cmb.Name = "cmb";
cmb.MaxDropDownItems = 4;
int no = 1001;
for (int i = 0; i < 100; i++)
{
no++;
cmb.Items.Add(no.ToString());
}
dataGridView1.RefreshEdit();
dataGridView1.Rows.Add();
}
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
if(e.ColumnIndex==0)// ItemId
{
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[4];
dataGridView1.CurrentCell.Value = "1";
dataGridView1.BeginEdit(true);
}
else if (e.ColumnIndex == 4)// NoofQty
{
dataGridView1.Rows.Add();
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex+1].Cells[0];
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This code works fine as per #Pranav-BitWiser Guidance ...

Error on Delete Last row of DataGridview on Winform Application in c#

I am working in Window application in asp.net. I have a GUI in which user enter a product name and quantity in text boxes. On Add button click i am adding a new row in Datagridview and set the value of productname and quantity in datagridview columns. I am not inserting record in Database and I am only save record in Datatable as well add record in Datagridview.
Problem is that when I select a last row from datagridview and press delete button from keyboard then it generate an error
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
static public DataTable gdt;
private void btnAdd_Click(object sender, EventArgs e)
{
try
{
if (txtItemCode.Text.Trim() == "")
{
MessageBox.Show("Enter Item Code");
txtItemCode.Focus();
return;
}
if (txtQty.Text.Trim() == "")
{
MessageBox.Show("Enter Qty");
txtQty.Focus();
return;
}
if (Convert.ToInt32(txtQty.Text.Trim()) <= 0)
{
MessageBox.Show("Qty must be greater than 0");
txtQty.Focus();
return;
}
if (btnAdd.Text == "ADD")
{
DataRow[] dr = gdt.Select("Item_Code = '" + txtItemCode.Text.Trim() + "'");
if (dr.Length > 0)
{
MessageBox.Show("Item Code Already Exist.");
txtItemCode.Text = "";
txtItemCode.Focus();
return;
}
tblItemMasterBLL oItem = new tblItemMasterBLL();
int ItemID = 0;
DataTable dt = new DataTable();
dt = oItem.getItemDetailByItemCode(txtItemCode.Text.Trim());
if (dt.Rows.Count > 0)
{
ItemID = Convert.ToInt32(dt.Rows[0]["Item_ID"]);
gdt.Rows.Add();
gdt.Rows[gdt.Rows.Count - 1]["Item_Code"] = txtItemCode.Text.Trim();
gdt.Rows[gdt.Rows.Count - 1]["Item_ID"] = ItemID;
gdt.Rows[gdt.Rows.Count - 1]["Qty"] = txtQty.Text.Trim();
gdt.Rows[gdt.Rows.Count - 1]["Article_Desc"] = Convert.ToString(dt.Rows[0]["Article_Desc"]);
gdt.Rows[gdt.Rows.Count - 1]["Color_Desc"] = Convert.ToString(dt.Rows[0]["Color_Desc"]);
gdt.Rows[gdt.Rows.Count - 1]["Size_Desc"] = Convert.ToString(dt.Rows[0]["Size_Desc"]);
gdt.Rows[gdt.Rows.Count - 1]["MRP"] = Convert.ToString(dt.Rows[0]["MRP"]);
dgv_Items.DataSource = null;
dgv_Items.DataSource = gdt;
}
else
{
MessageBox.Show("Invalid Item Code");
}
txtItemCode.Text = "";
txtQty.Text = "";
}
else if (btnAdd.Text == "UPDATE")
{
if (gdt.Rows.Count > 0)
{
gdt.Rows[Convert.ToInt32(lblhdnRowIndex.Text)]["Qty"] = txtQty.Text.Trim();
dgv_Items.Rows[Convert.ToInt32(lblhdnRowIndex.Text)].Cells["Qty"].Value = txtQty.Text.Trim();
}
txtItemCode.ReadOnly = false;
txtItemCode.Text = "";
txtQty.Text = "";
lblhdnItemID.Text = "";
lblhdnItemCode.Text = "";
lblhdnQty.Text = "";
btnAdd.Text = "ADD";
lblhdnRowIndex.Text = "";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void dgv_Items_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
try
{
if (MessageBox.Show("Do you want to delete the current row?", "Confirm deletion",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
ScrollPosition = 0;
ScrollPosition = dgv_Items.FirstDisplayedScrollingRowIndex;
int iIndex = dgv_Items.CurrentRow.Index;
gdt.Rows.RemoveAt(iIndex);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void dgv_Items_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
{
try
{
dgv_Items.DataSource = null;
dgv_Items.DataSource = gdt;
dgv_Items.Rows[dgv_Items.Rows.Count - 1].Visible = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
How about ..
ScrollPosition = 0;
dgv_Items.FirstDisplayedScrollingRowIndex=ScrollPosition;
int iIndex = dgv_Items.CurrentRow.Index;
gdt.Rows.RemoveAt(iIndex);
thanks all of u participate to solve my problem. Actually this is index problem.
I have find out the solution In which I have done changes in UserDeletingRow event of Datagridview. I have added a new line in UserDeletingRow eventhich is in bold font. Now my code is working fine.
private void dgv_Items_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
try
{
if (MessageBox.Show("Do you want to delete the current row?", "Confirm deletion",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
ScrollPosition = 0;
ScrollPosition = dgv_Items.FirstDisplayedScrollingRowIndex;
int iIndex = dgv_Items.CurrentRow.Index;
DataRow dr = gdt.Rows[iIndex]; //new added code
gdt.Rows.RemoveAt(iIndex);
gdt.Rows.InsertAt(dr, iIndex); //new added code
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Categories

Resources