How to capture previous values of columns in a GridView in C# - c#

After updating a row, I am trying to save the previous values of that row.
In other words, I came up with the following code bellow to grab the values of the labels in the grid-view. This code in
gridview1_RowEditing(object sender, GridViewEditEventArgs e)
{
string Name = "";
string day = "";
string Session_name = ((Label)gridview1.Rows[0].FindControl("Name")).Text;
strSession_Name = Session_name;
string Session_type = ((Label)gridview1.Rows[0].FindControl("day")).Text;
strType = Session_type;
}
When edit is clicked the labels turn into drop-down controls where the user can choose a different value. Later, after the user chooses the new value they want, they will click update. This will override the old value. However, when update fires I need somehow to save the old value to a string before it changes to the new one. when the update is running, RowUpdating(object sender, GridViewEditEventArgs e) is executed and the above values are null.

Why don't you do the following
Session["Name"] = ((Label)gridview1.Rows[0].FindControl("Name")).Text;
Session["Day"] = ((Label)gridview1.Rows[0].FindControl("day")).Text;
Then reference the Session["Name"] and Session["Day"] inside RowUpdating

Related

How to select a row in a DataGridView programmatically AND trigger DataGridView.SelectionChanged event?

For the life of me I cannot seem to figure this out. I have a long DataGridView (that does not allow MultiSelect) and when a user commits a change to the data, the data from the grid is purged and redrawn (because changes can affect multiple rows, this was the simpler approach). However, when I try to select the row programmatically, it does not also fire the DataGridView.SelectionChanged event, which I use to display data from an array which is correlated to the DataGridView current cell index. When doMagicStuff executes, the values for the wrong index (specifically, index 0) is show.
private void doMagicStuff()
{
int selRow = myDGV.CurrentCell.RowIndex;
myDGV.Rows.Clear();
/*Perform Task, Redraw data*/
myDGV.CurrentCell = myDGV[selRow, 0];
}
private void myDGV_SelectionChanged(object sender, EventArgs e)
{
Label1.Text = myDisplayValue1[myDGV.CurrentCell.RowIndex];
Label2.Text = myDisplayValue2[myDGV.CurrentCell.RowIndex];
TextBox1.Text = myEditValue1[myDGV.CurrentCell.RowIndex];
TextBox2.Text = myEditValue2[myDGV.CurrentCell.RowIndex];
}
Make sure that your client settings and OnSelectedIndexChanged is set like so: (ASP.NET AJAX)
.aspx page
<telerik:RadGrid ID="Grid1" runat="server" OnSelectedIndexChanged="Grid1_SelectedIndexChanged" OnItemDataBound="Grid1_ItemDataBound" OnPreRender="Grid1_PreRender">
<ClientSettings EnablePostBackOnRowClick="true">
<Selecting AllowRowSelect="true"></Selecting>
</ClientSettings>
</telerik:RadGrid>
aspx.cs page
protected void Grid1_SelectedIndexChanged(object sender, EventArgs e)
{
string value = null;
foreach(GridDataItem item in Grid1.SelectedItems)
{
//column name is in doub quotes
value = item["Name"].Text;
}
}
Add a button click to the form to test the selected values in the DataGridView.. double click that button then paste this code in there
foreach (DataGridViewRow row in myDGV.SelectedRows)
{
Label1.Text = //This should be hard coded the only thing that should change dynamically is the TextBox Values
Label2.Text = //This should be hard coded the only thing that should change dynamically is the TextBox Values
TextBox1.Text = row.Cells[0].Value.ToString();//change the 0 or 1 to fit your column Index position
TextBox2.Text = row.Cells[2].Value.ToString();
}
also if you have 4 columns and 4 text boxes then you will assign all of the textbox.Text values within the foreach loop just follow the pattern and increase the index by 1 so 2 textboxes means row.Cells[0] is the first column row.Cells[1] is the second column ...etc

Store ID of RowEditing Instead of Index

In my application, I give the user the option to search the database. When they click edit, I want the GridView to only show the row they are updating by storing its ID.
I'm trying the following code, but it is not returning anything other than the Control.
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
string value = GridView1.Rows[e.NewEditIndex].Cells[3].ToString();
}
Any ideas on how to store the value that I'm looking for?
Use the cell's Text property
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
string value = GridView1.Rows[e.NewEditIndex].Cells[3].Text;
// or
string value = GridView1.Rows[e.NewEditIndex].Cells[3].Value;
}
Or If you have declared the control as <TemplateField> for which you are trying to get the value for then try
string value = ""
Label lblID = (Label)GridView1.Rows[e.NewEditIndex].FindControl("lblID");
value = lblID.Text;
Another alternative would be to add DataKeyNames="ID" for the gridview which you can retrieve using
// assuming that the value of your datakey is numeric value
long Id = long.Parse(GridView1.DataKeys[e.NewEditIndex].Values["ID"].ToString());
Note you can add multiple comma separated values to DataKeyNames property.

NULL Empty Item in Bound ComboBox

How can I have an empty item in the bound ComboBox which uses NULL as the value for an Insert or Update?
With the code below, I can manually add the additional row. The column inspector_id is the primary key of an FK relationship. I have to set inspector_id = -1, since C# does not allow an int to be null. However, the insert (or update) fails since there is no inspector_id: -1 in the database.
private void ItemInfo_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'someDBDataSet.inspector' table. You can move, or remove it, as needed.
this.inspectorTableAdapter.ClearBeforeFill = false;
someDBDataSet.inspectorRow newRow = this.someDBDataSet.inspector.NewinspectorRow();
newRow.inspector_id = -1; // Since an int in C# cannot be null
newRow.fullName = "(none)";
newRow.employeeCode = "";
this.someDBDataSet.inspector.AddinspectorRow(newRow);
this.inspectorTableAdapter.Fill(this.someDBDataSet.inspector);
//this.inspectorTableAdapter.ClearBeforeFill = false;
// TODO: This line of code loads data into the 'someDBDataSet.item' table. You can move, or remove it, as needed.
this.itemTableAdapter.Fill(this.someDBDataSet.item);
}
Eureka! Bind to a view, not table.
Bind inspector_idComboBox to a new SQL Server view of the inspector table.
SELECT NULL as inspector_id, '(none)' as fullName, '' as employeeCode
UNION
SELECT inspector_id, fullName, employeeCode
FROM dbo.inspector
Pros:
The (none) item is in the ComboBox
The SelectedItem and text persists when selecting the item.
The SQL view allows a NULL value for inspector_id
No workarounds are needed in the application code. Just fill the DataSet from the view.
Allows more flexibility as the relationship is not bound.
... brilliant!
Another approach is to clear the ComboBox when selecting (none):
private void inspector_idComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (inspector_idComboBox.SelectedValue != null)
if ((int)inspector_idComboBox.SelectedValue == -1)
inspector_idComboBox.SelectedItem = null;
}
Pros:
The correct NULL value is saved to the DataSet and sent on to the database.
No external clear button is needed.
Cons:
Selecting (none) also clears the text. I'd prefer for (none) to stay selected.
After trying various approaches, I initially decided on the following:
private void ItemInfo_Load(object sender, EventArgs e)
{
this.inspectorTableAdapter.Fill(this.someDBDataSet.inspector);
this.itemTableAdapter.Fill(this.someDBDataSet.item);
}
private void noInspector_btn_Click(object sender, EventArgs e)
{
inspector_idComboBox.SelectedItem = null;
}
Rather than adding a dummy item into the ComboBox, I added a (link) button to clear the ComboBox.
Pros:
The ComboBox clears.
The tableAdapter sets item.inspector_id = NULL
Cons:
Other form controls bound to inspector fields remain unchanged (as there is no "empty" inspector row to use).
No text is displayed in inspector_idComboBox when SelectedItem is null. I'd prefer having something like (none) shown in the box.

How do I Grab Selected Index on two Dropdownlist's OnSelectedIndexChanged?

I am trying to use two DropDownLists to filter data. I set both of the OnSelectedIndexChanged Equal to the method below. The problem is it is only grabbing the SelectedIndex of the DDL that is changed. Example: if i choose a option in DDL1 it grabs that value and doesnt grab the value of DDL2. They both have the same OnSelectedIndexChanged i figured it would grab the current value of both. Is there a way to make it look at both DDL Controls?
protected void BrandsList_SelectedIndexChanged(object sender, EventArgs e)
{
int DDLcatId = CategoriesList.SelectedIndex;
int DDLBraId = BrandsList.SelectedIndex;
IQueryable<Product> DDLprodResult = GetProductsDDL(DDLcatId, DDLBraId);
if(DDLprodResult == null)
{
}
else
{
CatLab.Text = DDLprodResult.ToList().Count().ToString();
productList.DataSource = DDLprodResult.ToList();
productList.DataBind();
}
}
Your code should work. Of course only one can be changed if you have set AutoPostBack="true"(default is false) on both. But you should get the correct SelectedIndex anyway in the handler.
So i will guess: you are databinding the DropDownLists on every postback. Do this only if(!IsPostBack), otherwise you always overwrite changes with the original values.
So for example in Page_Load:
protected void Page_Load(Object sender, EvengtArgs e)
{
if(!IsPostBack)
{
// DataBind your DropDownLists
}
}

Link button changing color when any data pager event takes place

i have a alphabetic filter consist of 26 dynamically created link button on selecting any link button it is filtering the name of user's on the basis of alphabet and changing its color to orange to make it different from other linkbuttons it is working fine but if there are more number of user associated with a particular alphabet and on applying filter it is filtering the user on the basis of that alphabet and showing them in a list view on clicking the data pager next page or any other page number the link button changes its color to default color but i want to keep that highlighted until and unless other link button is selected
my code
protected void Page_Init(object sender, EventArgs e)
{
// Adding Dynamically linkbuttons for all alphabets(i.e. A-Z)
for (char asciiValue = 'A'; asciiValue <= 'Z'; asciiValue++)
{
LinkButton lbtnCharacter = new LinkButton();
lbtnCharacter.ID = "lbtnCharacter" + asciiValue;
divAlphabets.Controls.Add(lbtnCharacter);
// Setting the properties of dynamically created Linkbutton.
lbtnCharacter.Text = Convert.ToString(asciiValue);
lbtnCharacter.CssClass = "firstCharacter";
lbtnCharacter.ToolTip = "Show Tags starting with '" + Convert.ToString(asciiValue) + "'";
lbtnCharacter.CommandArgument = Convert.ToString(asciiValue);
lbtnCharacter.Command += new CommandEventHandler(lbtnCharacter_Command);
}
}
// For assigning default color to linkbutton text in page load
foreach (var ctrl in divAlphabets.Controls)
{
if (ctrl is LinkButton)
((LinkButton)ctrl).CssClass = "firstCharacter";
}
void lbtnCharacter_Command(object sender, CommandEventArgs e)
{
// Storing the values of pressed alphabet in viewstate.
ViewState["Selected_Character"] = e.CommandArgument;
LinkButton lbtnSelected = (LinkButton)divAlphabets.FindControl("lbtnCharacter" + e.CommandArgument);
lbtnSelected.CssClass = "firstCharacter highlighted";
txtTagFilter.Text = string.Empty;
BindTagList();
}
I hope I understood your question.
You are setting your Selected_Character item in the command handler and then setting the class of the button to highlight it. This only gets fired when the button is clicked, not when you move to the next page. Why not separate these two operations. Set the class of the link button on prerender if the Selected_Character matches. That way even when you page the link button will stay highlighted.
I would also set your selected character as a query string parameter, if someone copies and pastes a link to your page the button would not highlight and the correct data would not display.
Hope this helps.
Edit: Haven't tested the below but maybe it will get you started.
void lbtnCharacter_Command(object sender, CommandEventArgs e)
{
// redirect to self with tag as qs parameter
Response.Redirect(string.Format("{0}?tag={1}", Request.Url.GetLeftPart(UriPartial.Path), e.CommandArgument));
}
protected void Page_PreRender(object sender, EventArgs e)
{
if (Request.QueryString["tag"] != null) {
LinkButton lbtnSelected = (LinkButton)divAlphabets.FindControl("lbtnCharacter" + Request.QueryString["tag"]);
lbtnSelected.CssClass = "firstCharacter highlighted";
}
}
N.B You will also need to change your BindTagList to use the query string also. I'm assuming you call this in the page load event.

Categories

Resources