passing arguments with postback to page - c#

iv'e got an aspx page with some user controls , all of which contain a checkbox .
the checkbox is checked when the user control is added to the page.
the checkbox is set to auto post back
what i need is for when the auto post back occurs the user control will be gone.
first of all the way i load my user controls :
i load them as rows in a table and give their ID values the value of an entity that they represent
private void Load_Products(List<AppProduct> user_products)
{
HtmlTableRow row = null;
foreach(AppProduct p in user_products)
{
row = new HtmlTableRow();
tbl_products.Rows.Add(row);
CartProduct prd = (CartProduct)Page.LoadControl("~/UserControls/CartProduct.ascx");
prd.Title = p.Title;
prd.Price = p.Price.ToString();
prd.Pid = p.Pid.ToString();
prd.ID = p.Pid.ToString();
prd.State = 2;
prd.Product_Checked += new EventHandler(prd_Product_Checked);
HtmlTableCell cell = new HtmlTableCell();
cell.Controls.Add(prd);
row.Cells.Add(cell);
}
}
the CartProduct UserControl represents the AppProduct Entity
now the way i removed the product (usercontrol) was by removing it from the list as follows :
void prd_Product_Checked(object sender, EventArgs e)
{ // this removes the product from the same list that the load products function gets
ProductChangedEventArgs args = (ProductChangedEventArgs)e;
cart.RemoveProduct(uid, args.Pid);
Response.Redirect("~/Pages/cart.aspx");
}
now this works , but it seems wrong to have to postback and then redirect again in order to take affect the removal from the list occur's on the post back , but takes affect
only on the next page load, when the list is re-loaded .
if i could some how remove the item from the list during the page load of the post back
with out having to re-direct again.
any ideas how i could skip the redirect ?
i thought of maybe sending arguments with the postback but i don't know if that's even possible , cause then i could send the product id and remove it from the list before Load_Products is called .
thanks in advance
eran.

Instead of the Redirect why don't you simply call Load_Products again with the updated list of products?

Related

Error on passing data back to Dropdownlist asp .net webform

I have a dropdownlist that cannot be used for editing purpose. When button Edit is clicked inside listview where data exists, data is supposed to pass back to dropdownlist and other textboxes where the form is located outside listview. Passing data back to textboxes is ok. The problem is dropdownlist data that I want to edit was added to dropdownlist as another record. Please take a loot at picture, and I have to reselect the correct one. Otherwise, that selected data (e.g. December in picture) has no datavaluefield and it stops running if I didn't choose bottom December and click Update button. Here is my code for dropdownlist for months. Any help is appreciated for this. Thank you.
public void BindMonth()
{
ddlStartMonth.DataSource = objUIHelpers.GetAllMonths();
ddlStartMonth.DataTextField = "StartMonthName";
ddlStartMonth.DataValueField = "MonthId";
ddlStartMonth.DataBind();
ddlStartMonth.Items.Insert(0, "Select Start Month");}
Then, I put this method in page load like this.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindMonth();
}
}
This is listview data item editing
protected void lvEducation_ItemCommand(object sender, ListViewCommandEventArgs e)
{
switch (e.CommandName)
{
//Delete Method will be fired when command name "Delete" inside Listview is clicked.
case ("Delete"):
int EducationId = Convert.ToInt32(e.CommandArgument);//pass Id of Experience to identify datarow to delete
// DeleteEducationById(ExperienceId);//Call bind to delete method and pass ExperienceId as argument
break;
//Edit Method will fired when command name "Edit" inside Listview is clicked.
case ("Edit"):
EducationId = Convert.ToInt32(e.CommandArgument); //pass Id of Experience to identify datarow to edit
BindEducationDataToEdit(EducationId);//Call bind to edit method and pass ExperienceId as argument
break;
}}
This is part of method that triggers to pass back data to edit.
public void BindEducationDataToEdit(int EducationId)
{
Education edu = objJFUserBAL.GetEducationByIdToEdit(EducationId);
txtAdditionalInfo.Text = edu.AdditionalInfo.ToString();
ddlEndMonth.SelectedItem.Text = edu.mo.EndMonthName;
}
When selected data is posted back for editing, I have extra data like this.
You should not be updating the SelectedItem.Text. This is changing the displayed text. Instead you should be updating which item is selected.
If you do not have access to the value of the month name, you can do the following:
ddlEndMonth.Items.FindByText(edu.mo.EndMonthName).Selected = true;
which will select the item with the month text assuming one exists.
If it is possible to have an edu.mo.EndMonthName which does not exist in the list of items, you will want to do some checks for null and treat accordingly.
You have to fill a list manually, because auto binding is not going to let you put a "select your month" item unless you have one in your data base :
public void BindMonth()
{
List<Month> listOfMonth = new List<Month>();
Month fakeMonth = new Month();
// you need to see your own
//code and try to make a fake month with these parameters you want
fakeMonth.StartMonthName = "Select Start Month";
fakeMonth.MonthId = 0;
listOfmounth.Add(fakeMonth);
foreach(Month m in objUIHelpers.GetAllMonths())
{
listOfMonth.Add(m)
}
ddlStartMonth.DataSource = listOfMonth;
ddlStartMonth.DataTextField = "StartMonthName";
ddlStartMonth.DataValueField = "MonthId";
ddlStartMonth.DataBind();
ddlStartMonth.Items.Insert(0, "Select Start Month");}
}

How to avoid reloading GridView data every postback?

I have a GridView which loads some data on Load like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsPostBack)
{
DataTable dataSource = LoadObjects();
gvObjects.DataSource = dataSource;
}
}
I've also added a SelectedIndexChanged event handler where I want to perform some functions whenever a row is selected. The problem is that unless I remove the IsPostBack check from the OnLoad method, when a row is selected the GridView.SelectedRow attribute is not the row I selected.
Ideally I don't want to load all my data from the database on each postback. Are there any best-practices to get the selected row during the SelectedIndexChanged event without reloading everything again?
Thanks.
I usually have my GridViews full of dynamic controls which can be a lot of "fun", if they're not recreated on PostBack they don't work.
You seem only interested in the SelectedRow but this solution will also work and help save you a headache if you start getting fancy with dynamic controls
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
gvObjects.DataSource = LoadCachedObjects();
gvObjects.DataBind();
}
private DataTable LoadCachedObjects()
{
var result = new DataTable();
if ((Session["CachedDataTable"] != null) && (IsPostBack))
{
//cached DataTable will only be used on PostBack
result = Session["CachedDataTable"] as DataTable;
}
if (result.Rows.Count == 0)
{
result = LoadObjects(); //Get data from the database
Session["CachedDataTable"] = result;
}
return result;
}
This only loads the data from the session when a postback event occurs, so you'll have one initial database hit on page load. Also if you end up using that code on other pages you don't have to be massively concerned about giving the session variable a unique name
By default the GridView selects a row based on Index. Try instructing the GridView to select rows based on Keys.
Set the EnablePersistedSelection property to true so that the row selection is based on data-key values. Now if your earlier selected row gets its index or position changed in any way it will remain selected.
If you can't prevent postbacks, you will obviously have to reload.
So the solution would be to try to reload as little as possible.
A good way is to cache data somewhere, for example in the Session object.
But only cache the primary keys together with a result index (1 to total result count). This way, you can quickly retrieve the primary keys that you need data for, and get only that data freshly from the database.

How can I get the value of a dynamically created checkbox when the submit button is clicked?

I have a asp.net page that has two controls on it, A placeholder and a submit button. During the Page_Load I create a checklist of tasks dynamically. Each row consists of a description, link to a tutorial, and a checkbox. All of the information in the row is kept in a database. If the database says the task has been checked, the code sets the checked property to true. The problem I'm having is that when the submit button is clicked I cannot find what the value is of the checked property for all of the checkboxes on the page(about 23 total).
Here is the code to create the checkboxes...
checkbox = new CheckBox();
phChecklist.Controls.Add(checkbox);
if (item.Attributes.Contains("ree_completed"))
checkbox.Checked = (bool)item.Attributes["ree_completed"];
checkbox.EnableViewState = true;
checkbox.ClientIDMode = System.Web.UI.ClientIDMode.Static;
checkboxId = "checkbox" + (string)item.Attributes["ree_sectionnumber"].ToString() + (string)item.Attributes["ree_sequencenumber"].ToString();
checkbox.ID = checkboxId;
Here is the code to try and find the value of the checkbox...
foreach (Entity item in checklistCollection.Entities)
{
checkboxId = "checkbox" + (string)item.Attributes["ree_sectionnumber"].ToString() + (string)item.Attributes["ree_sequencenumber"].ToString();
itemChecked = (bool)ViewState[checkboxId];
if (itemChecked == "true")
** update database **
//CheckBox checkbox = (CheckBox)phchecklist.FindControl(checkboxId);
}
I think I've read every post on this subject and have tried most of them. I have also read about the ViewState but the suggestions that I have read about have not worked. As you can see I also tried finding the checkbox in the controls collection by the id and that also did not work.
I do not recreate the checkboxes when posting back to the page. Some posts mention that you have to recreate the controls but when I tried to do that I received an error message saying it was a duplicate id. The other reason I would prefer not to have to recreate the page is the performance hit. The database is in a Microsoft Dynamic CRM database that is remote.
How do I retain the value of checked property across a post back?
UPDATE: I changed my logic around and fixed the duplicate id error. The page will now recreate all of the controls during the post back. I still cannot find the value of any of the checkbox controls when the submit button is clicked.
Gary
You need to provide an ID for the checkbox control when you create it. Since you are creating multiple checkboxes; one for each row in the database ... you need to add the unique row identifier to the ID. So you need to build the checkbox ID from the row ID (usually the IDENTITY). Example: ">
Then on postback while you are post-processing each row in the table, you can query the request for that specific key value pair. Something similar to this:
foreach (DataRow dr in dataTable.Rows)
Response["chk_" + dr("ID")];
Use Page Init as opossed to page_Load event. As per https://msdn.microsoft.com/en-us/library/ms178472.aspx "Use this event to read or initialize control properties"
In case for that to work you need to add an event handler to dynamically added controls
in your case
checkbox = new CheckBox();
phChecklist.Controls.Add(checkbox);
checkbox.CheckedChanged += checkBox_CheckedChanged;
and then what you need to do in the method
private void CheckBox_CheckedChanged(object sender, System.EventArgs e)
{
...
}
As I commented, you certainly need to create your controls during the Init event, Load is too late. Check out the asp.Net page life's cycle for details.
On a side note, you might want to let ASP.NET handle the controls's ID. You say you need to keep some value in order to get back to the database, you can wrap your checkboxes in a table. You will then be able to iterate through your controls without having to guess their names.
For instance, if your row has a HiddenField followed by your actual CheckBox:
//Please call me during Init
protected void createTheControls() {
TableRow tr;
TableCell td;
CheckBox cb;
HiddenField section, sequence;
foreach (Object item in someList)
{
section = new HiddenField();
section.Value = item.Attributes["ree_sectionnumber"].ToString();
sequence = new HiddenField;
sequence.Value = item.Attributes["ree_sequencenumber"].ToString();
cb = new CheckBox();
cb.ID = String.Concat("checkbox", (String)sequence.Value);
if (item.Attributes.Contains("ree_completed"))
cb.Checked = (bool)item.Attributes["ree_completed"];
td = new TableCell();
td.Controls.Add(section);
td.Controls.Add(sequence);
td.Controls.Add(cb);
tr = new TableRow();
tr.Cells.Add(td);
}
}
protected void readTheControls()
{
foreach (TableRow tr in myTable.Rows)
{
HiddenField section = (HiddenField)tr.Cells[0].Controls[0];
HiddenField sequence = (HiddenField)tr.Cells[0].Controls[1];
CheckBox cb = (CheckBox)tr.Cells[0].Controls[2];
}
}
I notice you try to use the ViewState explicitly, which I believe is not going to be of any help here. The solution above may look cumbersome, but it will ensure you dont need to mess with ID's when fetching the controls.
Here's a thorough explanation from MSDN, and here are a few short and sweet SO answers explaining ViewState's purpose.

Why is my Linkbuttons command function not getting trigged?

I have this code in my codebehind:
for (int i = 0; i < linkList.Count; i++)
{
var link = UppercaseFirst(linkList[i]);
var linkButton = new LinkButton
{
Text = link + " > ",
ID = Convert.ToString(i),
CommandArgument = urlList[i]
};
linkButton.Command += new CommandEventHandler(lnkWeb_Click);
bcHolder.Controls.Add(linkButton);
}
and here is the lnkWeb_Click method:
protected void lnkWeb_Click(object sender, CommandEventArgs e)
{
var url = e.CommandArgument.ToString();
//code...
}
This method is not getting triggered when I click on one of those generated linkbuttons.
Anyone have any idea what the problem is?
Tried OnCommand="lnkWeb_Click" in the aspx file and the method got trigged, but not those that I generate by code. They dont even have OnCommand="lnkWeb_Click" attribute.
The problem here is with the control life cycle. If you want to handle events of some control properly - you have to add this control to the page on every page loading process, that is on every postback.
Look what happens in your case:
Initial button is clicked
During the post back your dynamic link buttons are added to the page, event handlers are assigned to them
User clicks on the newly generated link button
During post back these dynamic link buttons are not added to the page again, ASP.NET does not know the origin of a event so it does not call the handler.
To fix this you might need to store in the View State information about link buttons that have to be added (please do not store the controls themselves, that would be a huge overhead). Also pay attention to their IDs - they have to be the same for the same controls.
Update. Some more hints on the View State solution.
Basically you need some indicator that during the page loading you need to create some dynamic link buttons. The very basic way to do it is to store the list of the link button identifiers (or texts, or both) and then during Page_Load check if there is anything stored in View State. For example:
// Property to access the view state data
protected List<string> Links
{
get { return ViewState['links']; }
set { ViewState['links'] = value; }
}
...
protected void Page_Load(object sender, EventArgs e)
{
...
if (this.Links != null && this.Links.Count > 0)
{
// inside this method you create your link buttons and add them to the page
// you actually have this code already
RenderLinkButtons();
}
}
...
// Not sure about what name you have here
protected void InitialButtonHandlerName(object sender, EventArgs e)
{
List<string> linkList = ...; //your variable, guessing a type
// this is exactly the method you use already to add links to the page
// just one more action added to it - store info about these links into View State to use it on later post backs
this.Links = linkList;
RenderLinkButtons();
}
Please use it just a point in right direction - you might have different implementation depending on your requirements and preferences. But I hope concept is clear now.

Updating database with dynamically created textbox

I'm writing a cart function for a webpage project I have. On the cart page, it checks your cart ID in a cookie, and then gets all of your items in the database. So, every item in the Cart table is dynamically created. On the .aspx page, there is an empty table created. In the codebehind, a new row and cells are created for each item.
I'm having trouble with updating the Quantity of a certain item. For each item in the cart, a textbox and button are dynamically created for the quantity, and updating the quantity. The quantity is set to whatever the quantity is in the database on page load. I can't seem to get the value of the textbox after it has been changed, for example from 1 to 2.
Here's a summary of how the table is populated. I've shortened it a lot, just to show how i'm loading the data into the table.
protected void Page_Load(object sender, EventArgs e){
cartpopulate(cartID);
}
private void cartpopulate(int cartID){
//for each item in database where cartID is paramater cartID
//create a row
//get the product name, image, price, quantity, options, and make a cell for each
//calculate total price from quantity and price
//add in delete and quantity update buttons
For ease, lets just assume all the quantites are 1. So, on page_load, it will set all of the quantities to 1. I think my problem is that the following code sets the value of the textbox to whatever the quantity is when it's populated, which would be 1. When you change it to 2 or whatever, the value is already set and the 2 does nothing. The database updating part works, I'm just having trouble getting the second value '2'.
Here's the quantity update code...
if (prod.Quantity == null) { quantitylabel.Value = 1.ToString(); }
else { quantitylabel.Value = prod.Quantity.ToString() ; }
quantityinput.ID = "quantity" + i.ToString();
quantityinput.Width = 20;
quantityinput.Text = quantitylabel.Value.ToString();
quantitycell.Controls.Add(quantityinput);
quantitycell.CssClass="cartitem";
row.Cells.Add(quantitycell);
Button btnUpdate = new Button();
btnUpdate.Text = "Update";
string arg = quantityinput.Text;
btnUpdate.CommandName = "update";
btnUpdate.CommandArgument = arg;
btnUpdate.Command += (s, e) =>
{
string quanupdate = Convert.ToString(e.CommandArgument);
int quanint = Convert.ToInt32(quanupdate);
prod.Quantity = quanint;
db.SubmitChanges();
Response.Redirect("cart.aspx");
};
I've looked at a few different solutions, but none of them seem to work. Two things I suspect are the issue would be doing something on !IsPostBack, or recreating the dynamically created controls on postback. I'm self-taught at web programming, so I'm not 100% sure how to do that, but I think one of those are the issue.
Thanks in advance
try to use static variables i.e use prod.Quantity as static variable

Categories