I have two gridviews: parent and child. My goal is to update parent table with values from child table (this will be done in database). To complete this I need to read values from child gridview. I created below code but child rows are not read properly (I am gettin index is out of range error):
protected void btnUpdateSelected_Click(object sender, EventArgs e)
{
try
{
foreach (GridViewRow row_master in gvParent.Rows)
{
if (row_master.RowType == DataControlRowType.DataRow)
{
GridView gvChild = (GridView)gvParent.Rows[row_master.RowIndex].FindControl("gvChild");
if (gvChild != null)
{
foreach (GridViewRow row_child in gvChild.Rows)
{
if (row_child.RowType == DataControlRowType.DataRow)
{
CheckBox chckboxChild = (CheckBox)row_child.FindControl("chckboxChild");
if (chckboxChild.Checked == true & gvChild.Rows.Count == 1)
{
int index_master = Convert.ToInt32(row_master.RowIndex.ToString());
int index_child = Convert.ToInt32(row_child.RowIndex.ToString());
int rowID_a = Convert.ToInt32(gvParent.DataKeys[index_master].Values["ID"]);
int rowID_b = Convert.ToInt32(gvChild.DataKeys[index_master].Values["ID"]);
int serverID = Convert.ToInt32(gvParent.DataKeys[index_master].Values["ServerID"]);
int id = Convert.ToInt32(gvChild.DataKeys[index_child].Values["DeviceID"]);
int activeStatusID = Convert.ToInt32(gvChild.DataKeys[index_child].Values["ActiveStatusID"]);
string managedBy = gvChild.DataKeys[index_child].Values["ManagedBy"].ToString();
string monitoredBy = gvChild.DataKeys[index_child].Values["MonitoredBy"].ToString();
int managementProtocolID = Convert.ToInt32(gvChild.DataKeys[index_child].Values["ManagementProtocolID"]);
}
}
}
}
}
}
}
catch (Exception ex)
{
}
}
Related
i have the following Problem. I have a DatagridView with ComboBoxColumns. When i change the first ComboBox the second will be filled with data and when i select the first two the third will be filled.
It's working fine until here. My Problem is i have an add Button for new Rows and when i select the first ComboBoxColumn on the new (second) Row it will trigger also the values on the first Row and Update the second ComboBoxColumn on that row, but i only want to change the Values in a row not on all Rows.
Does someone have an Idea?
I tried to save the row number from where the Change came from, but i didn't affect anything.
Here's what i have so far:
private String id;
private int row_number;
//Fill first Combo
private void fill_first_combo()
{
datagridview_col1.Items.Clear();
if (datagridview.SelectedRows.Count > 0)
{
string rcs = db_conn.connection();
using (var OraConn = new OracleConnection(rcs))
{
using (var OraCmd = OraConn.CreateCommand())
{
try
{
OraConn.Open();
OraCmd.BindByName = true;
OraCmd.CommandText = "Oracle Command"
OracleDataReader OraDataReader = OraCmd.ExecuteReader();
if (OraDataReader.Read() == false)
{
//MessageBox
}
else
{
using (var OraDat = new OracleDataAdapter(OraCmd))
{
using (var table = new DataTable())
{
OraDat.Fill(table);
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
if (row[column] != null)
{
if (column.ColumnName == "COLUMNNAME")
{
datagridview_col1.Items.Add(row[column.ColumnName].ToString());
id = row[column.ColumnName].ToString().Substring(0, 6);
}
}
}
}
}
}
}
}
catch (OracleException ex)
{
//Exceptions
}
finally
{
OraConn.Dispose();
}
}
}
}
else
{
//MessageBox
}
}
//Fill 2nd ComboBoxColumn
private void fill_combobox2(int row_number)
{
datagridview_col2.Items.Clear();
string rcs = db_conn.connection();
using (var OraConn = new OracleConnection(rcs))
{
using (var OraCmd = OraConn.CreateCommand())
{
try
{
OraConn.Open();
OraCmd.BindByName = true;
OraCmd.CommandText = "Oracle Command with id as a Parameter";
var id_param = new OracleParameter("id", id);
OraCmd.Parameters.Add(id_param);
OracleDataReader OraDataReader = OraCmd.ExecuteReader();
if (OraDataReader.Read() == false)
{
//MessageBox
}
else
{
using (var OraDat = new OracleDataAdapter(OraCmd))
{
using (var combo2_table = new DataTable())
{
OraDat.Fill(combo2_table);
foreach (DataRow row in combo2_table.Rows)
{
foreach (DataColumn column in combo2_table.Columns)
{
if (row[column] != null)
{
if (column.ColumnName == "BUILDING_LESS")
{
datagridview_col2.Items.Add(row[column.ColumnName].ToString());
}
}
}
}
}
}
}
}
catch (OracleException ex)
{
//Catch Exceptions
}
finally
{
OraConn.Dispose();
}
}
}
}
//Trigger SelectionChange
private void datagridview_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox cb = e.Control as ComboBox;
if (cb != null)
{
cb.SelectedIndexChanged -= new EventHandler(selectionchange);
cb.SelectedIndexChanged += selectionchange;
}
}
private void selectionchange(object sender, EventArgs e)
{
try
{
//ComboBox cb = (ComboBox)sender;
String selected = (sender as ComboBox).SelectedItem.ToString();
if (datagridview.CurrentCell.ColumnIndex == 0)
{
row_number = datagridview.CurrentCell.RowIndex;
id = selected.Substring(0, 6);
if (!String.IsNullOrEmpty(id))
{
fill_combobox2(row_number);
}
else if (String.IsNullOrEmpty(id))
{
//MessageBox);
}
}
else if (datagridview.CurrentCell.ColumnIndex == 1)
{
section = selected.Substring(0, 2);
if (!String.IsNullOrEmpty(id) && !String.IsNullOrEmpty(value2))
{
//MessageBox
}
else if (String.IsNullOrEmpty(id) && !String.IsNullOrEmpty(value2))
{
//MessageBox
}
else if (String.IsNullOrEmpty(id) && String.IsNullOrEmpty(value2))
{
//MessageBox
}
}
}
catch (Exception ex)
{
//MessageBox
}
}
have you try using CellValueChange event to control this? Then you can do something like
The code is in VB but you may convert to C# using online tool
Try
Dim _ColumnIndex As Integer = datagridview.Columns("Combo1").Index
Dim _ColumnIndex2 As Integer = datagridview.Columns("Combo2").Index
If e.ColumnIndex = _ColumnIndex Then
'----your formula----
End If
Catch ex As Exception
End Try
I have created a paginated grid view which contains check boxes for multiple selection.But while looping through the data-row in the grid-view only last pages row values only I am able to get.I know it's because of the pagination.
My code is below
protected void btnSaveItemMapping_Click(object sender, EventArgs e)
{
grdCustomers.AllowPaging = false;
foreach (GridViewRow gvrow in grdCustomers.Rows)
{
CheckBox myCheckBox = (CheckBox)gvrow.FindControl("chkBoxBrandCustomers");
if (myCheckBox.Checked == true)
{
Label lblCustomerCode = (Label)gvrow.FindControl("lblCustomerCode");
//INSERT TO DATABSE
}
}
grdCustomers.AllowPaging = true
}
Keeping check box checked after changing page index like below code.
protected void grdCustomers_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
savechkdvls_cst();
grdCustomers.PageIndex = e.NewPageIndex;
if (Session["AllCustomers"] != null)
{
lstAllCustomers = (List<CustomerMaster>)Session["AllCustomers"];
}
grdCustomers.DataSource = lstAllCustomers;
grdCustomers.DataBind();
chkdvaluesp_cst();
}
private void chkdvaluesp_cst()
{
ArrayList usercontent = (ArrayList)Session["chkditems_customers"];
if (usercontent != null && usercontent.Count > 0)
{
foreach (GridViewRow gvrow in grdCustomers.Rows)
{
int index = Convert.ToInt32(grdCustomers.DataKeys[gvrow.RowIndex].Value);
if (usercontent.Contains(index))
{
CheckBox myCheckBox = (CheckBox)gvrow.FindControl("chkBoxBrandCustomers");
myCheckBox.Checked = true;
}
}
}
}
private void savechkdvls_cst()
{
ArrayList usercontent = new ArrayList();
int index = -1;
foreach (GridViewRow gvrow in grdCustomers.Rows)
{
index = Convert.ToInt32(grdCustomers.DataKeys[gvrow.RowIndex].Value);
bool result = ((CheckBox)gvrow.FindControl("chkBoxBrandCustomers")).Checked;
// Check in the Session
if (Session["chkditems_customers"] != null)
usercontent = (ArrayList)Session["chkditems_customers"];
if (result)
{
if (!usercontent.Contains(index))
usercontent.Add(index);
}
else
usercontent.Remove(index);
}
if (usercontent != null && usercontent.Count > 0)
Session["chkditems_customers"] = usercontent;
}
Any help will be appreciated.
I have a form. Which contains 2 tab.
First Tab is for instance Team1 info, where you can select player from datagridview. Selected player's info will populate in designated textboxes.
In tab 2 Team2, and exactly same concept.
I do use same exactly code to update Team 1(Tab1) player's info,and I works. But not for Team 2(Tab 2) player's.
This is screen shot of my code[![enter image description here][1]][1]
Team 1
private void updateButton_Click(object sender, EventArgs e)
{
//Local Variable
int barID = 0;
if (team1DataGridView.CurrentRow != null)
{
//Get row index
int rowIndex = team1DataGridView.CurrentRow.Index;
//Pass to local Variable
barID = Convert.ToInt32(team1DataGridView.Rows[rowIndex].Cells[0].Value);
}
var updatePlayers = (from p in _dbContext.barcelonaTeams
where p.ID == barID
select p).SingleOrDefault();
if (updatePlayers != null)
{
updatePlayers.LastName = lastNameTextBox.Text;
updatePlayers.FirstName = firstNameTextBox.Text;
updatePlayers.Phone = cellNumberTextBox.Text;
updatePlayers.PlayersPosition = playerPositionComboBox.Text;
}
try
{
//Submit Changes
_dbContext.SubmitChanges();
//Refresh datagridview'
team1DataGridView.Refresh();
}
catch (Exception exception)
{
//Display an error message
MessageBox.Show(exception.Message);
}
}
Team 2
private void mUpdateButton_Click(object sender, EventArgs e)
{
//Local variable
int barID = 0;
if (team2DataGridView.CurrentRow != null)
{
//Get row index
int rowIndex = team2DataGridView.CurrentRow.Index;
//Pass to local Variable
barID = Convert.ToInt32(team2DataGridView.Rows[rowIndex].Cells[0].Value);
}
var updatePlayers = (from p in _dbContext.manchesterUnitedTeams
where p.ID == barID
select p).SingleOrDefault();
if (updatePlayers != null)
{
updatePlayers.LastName = mLastNameTextBox.Text;
updatePlayers.FirstName = mFirstNameTextBox.Text;
updatePlayers.Phone = mCellNumberTextBox.Text;
updatePlayers.PlayersPosition = mPositionComboBox.Text;
}
try
{
//Submit to datagridview
_dbContext.SubmitChanges();
//Refresh datagridview
team2DataGridView.RefreshEdit();
}
catch (Exception exception)
{
//Show an error message
MessageBox.Show(exception.Message);
}
}
I think your dbContext.Submit method is just not actually submitting the value of the data members of 2 tab . Its just sending the values of your team 1 variables once again
I have a program which basically creates, reads, edits, and delete from a linq database.
It does function well on different rows, however when I select the first row to delete it, it acts as if there is no ROW selected so it returns me a "Select Row" output warning.
In addition when I click modify on the first row, it always edits the row below it only. (The other rows are not affected)
This is the 'event update' code in the class :-
public int UpdateEvent(int selectedRow, string name, DateTime date, string eventType, string eventVenue)
{
EventTicketEntities database = new EventTicketEntities();
Event selected = database.Events.Where(x => x.EventId == selectedRow).FirstOrDefault(); //selected row will give the id of the row
if (selected == null)
{
return -1;
}
else
{
selected.EventName = name;
selected.EventDate = date;
selected.EventType = eventType;
selected.EventVenue = eventVenue;
return database.SaveChanges();
}
}
This is the code of the 'event delete' in the class:-
public int DeleteEvent(int selectedRow)
{
EventTicketEntities database = new EventTicketEntities();
Event eventDelete = database.Events.Where(x => x.EventId == selectedRow).FirstOrDefault();
database.Events.Remove(eventDelete); //We use this method to delete the particular customer
return database.SaveChanges(); //returns the affected rows ....
}
This is the code of the button of the form:-
private void btnModify_Click(object sender, EventArgs e)
{
if (SelectedRow != -1) //if not selected do nothing
{
if (MessageBox.Show("Are you sure?", "Modify", MessageBoxButtons.YesNo, MessageBoxIcon.Stop) == DialogResult.Yes)
{
EventBL eBL = new EventBL();
int result = eBL.UpdateEvent(SelectedRow, eventName.Text, calendar.Value, cmbEventType.SelectedValue.ToString(), cmbEventVenue.SelectedValue.ToString());
MessageBox.Show(result + " rows affected!" + SelectedRow);
dgvEvents.DataSource = eBL.GetEvents();
dgvEvents.Refresh();
}
}
else
{
EventBL eBL = new EventBL();
MessageBox.Show("Select Row first" + SelectedRow);
dgvEvents.DataSource = eBL.GetEvents();
dgvEvents.Refresh();
}
}
This is the code of the delete button:-
private void btnDelete_Click(object sender, EventArgs e)
{
if (SelectedRow != -1) //if not selected do nothing
{
if (MessageBox.Show("Are you sure?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Stop) == DialogResult.Yes)
{
EventBL eBL = new EventBL();
int result = eBL.DeleteEvent(SelectedRow);
MessageBox.Show(result + " rows affected!");
dgvEvents.DataSource = eBL.GetEvents();
SelectedRow = -1;
}
}
else
{
MessageBox.Show("Select Row first");
}
}
And this is the code of the event handler of data grid view:-
private void dgvEvents_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex > 0)
{
SelectedRow = int.Parse(dgvEvents[0, e.RowIndex].Value.ToString());
}
}
Your help is much appreciated.
Take care-
HurpaDerpa
by the way، selected will always get a value it can't be null
So the condition
If (selected==null)
Will always be false
Because you assign .firstordefault
I have a GridView and I'm performing a bulk update for only one column with textbox. But before update I need to check the values of that textbox for entire gridview and if the values aren't changed I need to provide an alert stating "Make change to field to update".
Can anyone suggest me some options?
protected void btnUpdate_Click(object sender, EventArgs e)
{
try
{
foreach (GridViewRow row in gvDetails.Rows)
{
string strID = ((Label)row.FindControl("lblID")).Text;
string strGroup = ((Label)row.FindControl("lblGrp")).Text;
string strValue = ((TextBox)row.FindControl("txtValue")).Text;
{
//my update query
}
}
}
catch (Exception ex)
{
}
}
A much simpler method will be to add an asp:HiddenField to your ItemTemplate and compare the value for each row.
<asp:HiddenField ID="" runat="server" Value='<%# Eval("blah") %>'></asp:HiddenField>
Now all you need is to compare that value with the textbox value in each row in code-behind like this.
protected void btnUpdate_Click(object sender, EventArgs e)
{
try
{
var isAnyRowUpdated = false;
foreach (GridViewRow row in gvDetails.Rows)
{
string strID = ((Label)row.FindControl("lblID")).Text;
string strGroup = ((Label)row.FindControl("lblGrp")).Text;
string strValue = ((TextBox)row.FindControl("txtValue")).Text;
string strOldValue = ((HiddenField)row.FindControl("hdnOldValue")).Value;
if (strValue != strOldValue)
{
isAnyRowUpdated = true;
//update procedure here.
}
}
//now check if the flag is still false
//that means no rows are changed
if(!isAnyRowUpdated)
{
//alert no rows are updated
}
}
catch (Exception ex)
{
}
}
I hope the code is self explanatory.
You can try to use DataGridView.RowValidating Event and check if IsCurrentRowDirty Property is changed
IsCurrentRowDirty Property Gets a value indicating whether the current
row has uncommitted changes.
EDIT:-
The above works in Winforms; in Asp.net there is no such method, you have to load the data in a object and then you have to validate.
You can check Updating Only Changed Rows Using GridView Control
The basic thing to do here to load your original data into a DataTable and then compare the GridView rows, one by one in a loop for that particular Column, which in your case is the TextBox column. For comparing the DataTable with the GridView, you can try something like this :
foreach (GridViewRow row in Grd.Rows)
{
TextBox txtAmt = (TextBox)row.FindControl("txtAmount");
string Id = Grd.DataKeys[row.RowIndex].Value.ToString();
for (int i = 0; i < dt.Rows.Count; i++)
{
if (Id == dt.Rows[i]["ID"].ToString())
{
//do your logic here.
}
}
}
Hope this helps.
As per the conversation, I have provided some pseudo logic. You can implement your own code using this.
protected void btnUpdate_Click(object sender, EventArgs e)
{
try
{
DataTable dt = LoadData(); //Load the data from DB
EnumerableRowCollection<DataRow> enumerableDt = dt.AsEnumerable();
foreach (GridViewRow row in gvDetails.Rows)
{
string strID = ((Label)row.FindControl("lblID")).Text;
string strGroup = ((Label)row.FindControl("lblGrp")).Text;
string strValue = ((TextBox)row.FindControl("txtValue")).Text;
DataRow dr = enumerableDt.Where(x => x.Field<string>("ID") == strID).FirstOrDefault(); //Change your condition accordingly
if (dr["Value"].ToString().ToUpper() != strValue.Trim().ToUpper()) //Change your condition here
{
//Do your updated data logic here
}
else
{
//Do your not updated data logic here
}
}
}
catch (Exception ex)
{
}
}
Check them against the datakey value for the corresponding item.
<MasterTableView DataKeyNames="Response, ...
foreach (GridDataItem item in FTReport.MasterTableView.Items)
{
string ResponseValue = tbResponse.Text;
if (item.GetDataKeyValue("Response").ToString() != ResponseValue)
{
do something;
}
}
use onrowdatabound property of gridview. Inside it, use:
protected void GridLocation_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow &&
(e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
// here you can check your textbox values
}
}