Framework: ASP.NET 4.5 | Database: MSMMS
My demo application is supposed to populate textboxes with dynamic data when a selection is made from a dropdown list. I've added a button, that when pressed fires, an OnClick event that is supposed to assign values from the DB to the appropriate textboxes. Right now my code looks like:
protected void btnChoose_Click(object sender, EventArgs e)
{
API_DatabaseEntities1 db = new API_DatabaseEntities1();
var customer = (from c in db.Customers
where c.CustomerID == 4
select c).FirstOrDefault();
if (customer == null)
{
return;
}
if (ddlCustomer.SelectedValue == "Marisol") {
tbDescription.Text = customer.ToString();
tbFName.Text = customer.Fname;
tbSocial.Text = customer.SSN;
tbDOB.Text = customer.DOB.ToString();
tbFName1.Text = customer.Fname;
tbMName.Text = customer.Mname;
tbLName.Text = customer.Lname;
tbPrimaryPhone.Text = customer.PrimaryPhone;
tbSecondaryPhone.Text = customer.SecondaryPhone;
tbAdd1.Text = customer.Address;
tbCity.Text = customer.City;
tbZip.Text = customer.Zip;
tbEmail.Text = customer.Email;
tbMonLease.Text = customer.MortLeaseAmt;
tbEmployer.Text = customer.Employer;
tbPosition.Text = customer.Position;
tbHireDate.Text = customer.HireDate.ToString();
tbWorkPhone.Text = customer.WorkPhone;
tbGross.Text = customer.GrossIncome;
}
Debug.WriteLine(tbPosition.Text);
}
When the button is clicked, the page sends a request to the DB, but the textboxes remain blank. I am returning a value from the database, but it's not populating. Here is some code from my front page:
<form id="form1" runat="server">
<asp:DropDownList ID="ddlCustomer" runat="server" DataSourceID="SqlDataSource1" DataTextField="Fname" DataValueField="CustomerID"></asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:APIConnectionString %>" SelectCommand="SELECT [CustomerID], [Fname], [Lname] FROM [Customer] ORDER BY [Fname]"></asp:SqlDataSource><br /><br />
<asp:Button ID="btnChoose" runat="server" Text="Choose Test Case" OnClick="btnChoose_Click" /><br /><br />
Description of Goods and/or Services:<asp:TextBox ID="tbDescription" runat="server"></asp:TextBox><br /><br />
<div>
Membership #:<asp:TextBox ID="tbMembership" runat="server"></asp:TextBox> Ext.: <asp:TextBox ID="tbExt1" runat="server"></asp:TextBox>
First Name:<asp:TextBox ID="tbFName" runat="server"></asp:TextBox><br /> <br /><br />
Soc Sec No.: <asp:TextBox ID="tbSocial" runat="server"></asp:TextBox> Date of Birth:<asp:TextBox ID="tbDOB" runat="server" ></asp:TextBox>
</div><br /> <br />
I'm not sure if the problem is from the code behind or from the front page design. Any help would be appreciate. Thank you.
It looks like your code is checking for a selection in the drop-down list of the name "Marisol" - however, the "Value" field of the drop-down list is configured to use the CustomerID column. So this code populating the fields will never execute.
Maybe you should instead be using ddlCustomer.SelectedValue in the WHERE clause of your query.
Related
I have a DataList in ASP.NET that brings me the products from the "Products" table, so with the "Eval" statement I assign the product ID:
<asp:TextBox ID="idProductoText" runat="server" type="hidden" value='<%# Eval("PRO_ID") %>'></asp:TextBox>
So in my C# code I need to get the value of that TextBox by its ID, for example an idProductText.Text.Trim(); , but for some reason it doesn't work, any solution? I leave the complete DataList below.
Code to fill the DataList:
public void loadStockProducts()
{
OracleConnection connection = new OracleConnection(with);
OracleCommand command = new OracleCommand("SHOW_PRODUCTS_BUY", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Add("registers", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
OracleDataAdapter d = new OracleDataAdapter();
d.SelectCommand = command;
DataTable dt = new DataTable();
d.Fill(dt);
DataList1.DataSource = dt;
DataList1.DataBind();
connection.Close();
}
Full DataList in ASP.NET
<asp:DataList ID="DataList1" runat="server">
<ItemTemplate>
<div class="card mb-6" style="max-width: 1400px">
<div class="row g-0">
<div class="col-md-4">
<img
src="../../img/armchair.jpg"
class="img-fluid rounded-start"
alt="product" />
</div>
<div class="col-lg-5 m-4 form-floating">
<div class="card-body">
<!-- THE PRODUCT ID IS HIDDEN, IT WILL ONLY BE USED TO ADD TO CART -->
<asp:TextBox ID="idProductoText" runat="server" type="hidden" value='<%# Eval("PRO_ID") %>'></asp:TextBox>
<asp:Label ID="PRO_NAMELabel" class="card-title" runat="server" Text='<%# Eval("PRO_NAME") %>' Font-Bold="true" Font-Size="Large" Visible="True" />
<br />
<br />
Q<asp:Label ID="PRO_PRICELabel" class="card-text" runat="server" Text='<%# Eval("PRO_PRICE") %>' Font-Size="Large" />
<br />
<br />
<div class="input-group">
<asp:Button ID="moreInformation" runat="server" Text="More Information" class="btn btn-dark m-2" />
<asp:TextBox ID="quantidadBuy" runat="server" type="number" class="form-control m-2" placeholder="Quantity to Buy"></asp:TextBox>
<asp:Button ID="addCart" runat="server" Text="Add to Cart" class="btn btn-success m-2"/ OnClick="addCart_Click"/>
</div>
</div>
</div>
</div>
</div>
<br />
</ItemTemplate>
</asp:DataList>
Ok, while there are some events of the data list, you can just grab and get all the information you need/want from that button click you have.
However, before we write that code, I see you need a database row PK id, so, I suggest you remove this:
<!-- THE PRODUCT ID IS HIDDEN, IT WILL ONLY BE USED TO ADD TO CART -->
<asp:TextBox ID="idProductoText" runat="server"
type="hidden" value='<%# Eval("PRO_ID") %>'></asp:TextBox>
Assuming PRO_ID is the PK database id, then we really don't want to have that information in the markup - (even hidden).
So, use the so called "data keys" feature. You COULD leave the above, but remove it - we really don't need it.
So, in datalist, add this setting:
<asp:DataList ID="DataList1" runat="server" DataKeyField = "PRO_ID" >
Ok, so now the click event for the button.
Say we have this button:
<asp:Button ID="cmdView" runat="server" Text="View" CssClass="btn"
OnClick="cmdView_Click" />
Code behind:
protected void cmdView_Click(object sender, EventArgs e)
{
Button cmdView = sender as Button;
DataListItem gRow = cmdView.NamingContainer as DataListItem;
// get row index
Debug.Print("row click = " + gRow.ItemIndex.ToString());
// get database primary key (data keys)
int? PkID = DataList1.DataKeys[gRow.ItemIndex] as int?;
Debug.Print("Database PK id = " + PkID);
// get value of single control - say hotel label called
Label lHotelName = gRow.FindControl("HotelNameLabel") as Label;
Debug.Print("Hotel name = " + lHotelName.Text);
}
Output:
So note several things:
We grab/get current row - naming container. This works for Gridview, repeater, listview - quite much all of the data bound types of controls.
From that row, then we can get:
Row index -
From Row index, we reference into data keys. Note that datalist ONLY supports ONE data key, so in MOST cases, we have to do this .DataKeys[ some index]["SOME KEY"]
But datalist is a exception - only one key, so .DataKeys[some index] is all you require.
And to pull controls out, use .FindControl as I show above.
FYI: debug.print - this requires using System.Diagnostics;
(and I have my outputs re-directed to Immediate window).
Assignment Instructions:
Develop a simple shopping cart application that uses session objects to store the information. You will have to create an ASP.NET project that contains two web forms. The first web form, ShoppingCart.aspx, allows the user to select items using a set of checkboxes. This page shows also the number of items in the cart.
The second web form, Display.aspx, displays the number of selected items in a table and allows the user to go back to the first web form and continue shopping.
I am using a CheckBoxList to list my products, and I built a table with IDs in the cells to receive the data the user checks off.
(I considered the idea of using CheckBox vs. CheckBoxList, but this would not be the appropriate solution and doesn't easily allow counting total items selected)
I have tried using cookies and session state variables, but I can't figure out how to associate them to the table.
I can transfer test data from labels and textboxes, anything with an ID, but not my CheckBoxList items.
How do I reference which checkboxes are selected on page 1, that will update the desired table cells on page 2, after clicking the 'checkout' button without unique IDs on the list items?
Example: If... 1lb Dark Roast is selected on page 1 ...
(identified as 'p001' for product 1 on next page)
<asp:ListItem Value="15.99">1lb Dark Roast</asp:ListItem>
On page 2 (Display.aspx) the Amount column should update to '1' beside that product
<asp:TableCell ID="p001_amt" runat="server"></asp:TableCell>
If an item is checked on page 1, this should be the result... (along with the other products).
Product
Price
Amount
1lb dark Roast
$15.99
1
1lb Med Roast
$15.99
0
1 = checked, 0 = unchecked (assignment desired outcome shows this table)
Any help would be appreciated. Thanks.
Here are snippets from my code, if more is needed I can add a link to the full pages.
Page 1 (ShoppingCart.aspx)
ShoppingCart.aspx
------------------
<asp:Label ID="TotalCart_lbl" runat="server" Text="Total Items in your Cart: "></asp:Label>
<br />
<asp:CheckBoxList ID="Shop_ckbx" runat="server">
<asp:ListItem Value="15.99">1lb Dark Roast</asp:ListItem>
<asp:ListItem Value="15.99">1lb Medium Roast</asp:ListItem>
<asp:ListItem Value="12.99">1lb Decaf Roast</asp:ListItem>
<asp:ListItem Value="16.99">1lb Cold Brew</asp:ListItem>
<asp:ListItem Value="10.99">1 box Tea</asp:ListItem>
<asp:ListItem Value="35.99">French Press</asp:ListItem>
<asp:ListItem Value="8.99">CCM Mug</asp:ListItem>
</asp:CheckBoxList>
<br />
<asp:Button ID="UpdateCart_btn" runat="server" Text="Update Your cart" OnClick="UpdateCart_btn_Click"/>
<br />
<asp:Label ID="Contents_lbl" runat="server" Text="Update To See Cart Contents"></asp:Label>
<br />
<asp:Label ID="Cost_lbl" runat="server" Text="Total: "></asp:Label>
<br />
<asp:Button ID="Checkout_btn" runat="server" PostBackUrl="~/Display.aspx" Text="Go to Checkout" />
ShoppingCart.aspx.cs
---------------------
protected void UpdateCart_btn_Click(object sender, EventArgs e)
{
int total = 0; //Total item count
Contents_lbl.Text = "Your Cart Contains: <br/>- - - - - - - - - - - - - - - -";
foreach (ListItem listItem in Shop_ckbx.Items)
{
if (listItem.Selected == true)
{
//Add Text to label
Contents_lbl.Text += "<br/>• " + listItem.Text;
//Count Items in Cart
total += 1;
}
}
Contents_lbl.Text += "<br/>";
for (int i = 0; i < Shop_ckbx.Items.Count; i++)
{
if (Shop_ckbx.Items[i].Selected)
{
cost += Convert.ToDouble(Shop_ckbx.Items[i].Value);
Cost_lbl.Text = "Total: $ " + cost.ToString();
}
}
//Update total items
TotalCart_lbl.Text = "Total Items in Your Cart: " + total;
}
protected void Checkout_btn_Click(object sender, EventArgs e)
{
How do I reference the items in the checklist on page 1
to update the table on page 2 without unique IDs on each list item?
}
Page 2 code (Display.aspx)
Display.aspx
------------------
<asp:Table ID="Display_tbl" runat="server">
<asp:TableRow runat="server" ID="Header_row" Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99">
<asp:TableCell ID="Product_cell" runat="server" Width="250">Product</asp:TableCell>
<asp:TableCell ID="Price_cell" runat="server" Width="100">Price</asp:TableCell>
<asp:TableCell ID="Amount_cell" runat="server" Width="100">Amount</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p001">
<asp:TableCell ID="p001_prod" runat="server">1lb Dark Roast</asp:TableCell>
<asp:TableCell ID="p001_price" runat="server">$ 15.99</asp:TableCell>
<asp:TableCell ID="p001_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p002" Width="500px">
<asp:TableCell ID="p002_prod" runat="server">1lb Med Roast</asp:TableCell>
<asp:TableCell ID="p002_price" runat="server">$ 15.99</asp:TableCell>
<asp:TableCell ID="p002_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p003">
<asp:TableCell ID="p003_prod" runat="server">1lb Decaf</asp:TableCell>
<asp:TableCell ID="p003_price" runat="server">$ 12.99</asp:TableCell>
<asp:TableCell ID="p003_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p004">
<asp:TableCell ID="p004_prod" runat="server">1lb Cold Brew</asp:TableCell>
<asp:TableCell ID="p004_price" runat="server">$ 16.99</asp:TableCell>
<asp:TableCell ID="p004_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p005">
<asp:TableCell ID="p005_prod" runat="server">1 box Tea (50 bags)</asp:TableCell>
<asp:TableCell ID="p005_price" runat="server">$ 10.99</asp:TableCell>
<asp:TableCell ID="p005_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p006">
<asp:TableCell ID="p006_prod" runat="server">French Press</asp:TableCell>
<asp:TableCell ID="p006_price" runat="server">$ 35.99</asp:TableCell>
<asp:TableCell ID="p006_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="p007">
<asp:TableCell ID="p007_prod" runat="server">CCM Coffee Mug</asp:TableCell>
<asp:TableCell ID="p007_price" runat="server">$ 8.99</asp:TableCell>
<asp:TableCell ID="p007_amt" runat="server"></asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server" ID="Total_row">
<asp:TableCell ID="Total_prod" runat="server">Total</asp:TableCell>
<asp:TableCell ID="Total_price" runat="server"></asp:TableCell>
<asp:TableCell ID="Total_amt" runat="server"></asp:TableCell>
</asp:TableRow>
</asp:Table>
<asp:LinkButton ID="Back_linkbtn" runat="server" OnClick="Back_linkbtn_Click">Go Back to the Shop</asp:LinkButton>
Display.aspx.cs
-------------------
protected void Page_Load(object sender, EventArgs e)
{
ShoppingCart prevPage = PreviousPage as ShoppingCart;
if (prevPage != null)
{
NOT SURE HOW TO LINK TO MY CHECKLIST ITEMS
TO UPDATE 'AMOUNT' TABLE CELLS
Also,
CHECKBOXES ON PREVIOUS PAGE NEED TO STAY SELECTED
in order to CONTINUE SHOPPING.
}
}
protected void Back_linkbtn_Click(object sender, EventArgs e)
{
Response.Redirect("ShoppingCart.aspx");
}
Ok, so the problem we have here is of course matching up the “thing” you selected on one page, and then figuring this out on the next web page.
To be fair, the problem here is that no doubt you have to "make up" the data here. And that REALLY hurts this whole process, since you having to type in the data two times (once on this page, and then on the target page). Worse, you have to match up by "text". One little space, period etc. and your whole system will fall down.
I going to suggest we NOT worry and NOT have to match up the values. We can in one shot get rid of a HUGE problem, and ALSO reduce the markup, the code and all your life hassles (well, ok, just the coding part - can't fix everything!!!).
So, I going to suggest that in place of the check box "list", we create a table and use that for BOTH pages. This will then not only keep us out of rooms with padded walls, but we can deal with a "row" of something that you select, and just not give one hoot as to the spelling or even what we place in that row. And by doing this, you could with almost no code changes change the "list" from our table to a database - and the whole she-bang would work!!
So, lets use (create) a table, and not only is this easy, but I think far more clean to setup our data.
So, we will have this at the start of the page (a table and some total values for the WHOLE page class.
public class MyFirstOrderPage : System.Web.UI.Page
{
private DataTable MyTable = new DataTable();
private decimal MyTotal = 0;
private int MyTotalQty = 0;
Ok, now lets do the sub in this page to load up the above table.
public void CreateData()
{
MyTable.Columns.Add("Product", typeof(string));
MyTable.Columns.Add("Price", typeof(decimal));
MyTable.Columns.Add("Qty", typeof(int));
MyTable.Columns.Add("Amount", typeof(decimal));
MyTable.Columns.Add("Purchased", typeof(bool));
MyTable.Rows.Add({"11b Dark Roast",15.99,1,0,false});
MyTable.Rows.Add({"11b Medium Roast",15.99,1,0,false});
MyTable.Rows.Add({"1b Decaf Roast",12.99,1,0,false});
MyTable.Rows.Add({"11b Cold Brew",16.99,1,0,false});
MyTable.Rows.Add({"1 box Tea Brew",10.99,1,0,false});
MyTable.Rows.Add({"French Press",35.99,1,0,false});
MyTable.Rows.Add({"CCM Mug",8.99,1,0,false});
}
Now not only can you "easy" read the above, but you can change/view and see the columns and then the data follows - so you can see we decided to have a Qty and also a column for the purchased. this will save BUCKETS of code, and BUCKETS of markup. And we can use the above to BOTH pages - no having to have two copies of this list!!!!
Ok, so now we have our table. next up, lets display that table. And we can use VERY much the same grid in our order page as we can in the check out page (saves even more time, more code and even MORE markup!!!).
So, lets use a gridview. We could use a listview and I would consider that if you wanted a cute picture and some more product description. But, gridview is fine.
So, here is the markup for the gridview:
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" ShowFooter="true"
Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Product" HeaderText="Product" Headerstyle-width="250px" />
<asp:BoundField DataField="Price" DataFormatString="{0:C2}" HeaderText="Price" Headerstyle-width="80px" />
<asp:TemplateField HeaderText="Qty" >
<ItemTemplate>
<asp:TextBox ID="Qty" runat="server" Width="60px"
Text ='<%# Eval("Qty") %>'
MyRow = '<%# Container.DataItemIndex %>'
AutoPostBack="true" OnTextChanged="Qty_TextChanged"
/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Amount">
<ItemTemplate>
<asp:TextBox ID="Amount" runat="server" width="80px"
Text ='<%# FormatCurrency(Eval("Qty") * Eval("Price")) %>' Enabled="false" DataFormatString="{0:C2}" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Purchase" ItemStyle-HorizontalAlign="Center">
<ItemTemplate >
<asp:CheckBox ID="CheckBox1" runat="server" width="110px"
Checked ='<%# Eval("Purchased") %>'
MyRow = '<%# Container.DataItemIndex %>'
AutoPostBack="true"
OnCheckedChanged="CheckBox1_CheckedChanged1"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
</asp:GridView>
<asp:HiddenField ID="qtycheck" runat="server" ClientIDMode="Static" />
<br />
<asp:Button ID="Checkout_btn" runat="server" Text="Proceed to Checkout"
style="width:140px;height:60px;background-color:#FFCC99;border-radius:25px"
OnClientClick="hasorder();return false;"/>
<script>
function hasorder() {
var CheckQty = document.getElementById("qtycheck")
if (CheckQty.value > 0) {
window.location.href = "/CheckOut.aspx"
}
else {
alert("Please select at least one Purchase before proceding to check out");
return false;
}
}
</script>
Now that is a bit of markup, but it is STILL much less then say your 2nd page table, and better you see how our 2nd page now is VERY little markup!!
Ok, so we have the above. The only real issue is that when you check a box, we need to total things up. And when you edit or change the qty, then SAME thing - update the totals.
So, the code we have for each part is again rather limited. I'll post in all in one shot:
protected void Page_Load(object sender, System.EventArgs e)
{
if (System.Web.UI.Page.IsPostBack == false)
{
// ok first page load, now check if reutrn from checkout
if (System.Web.UI.Page.Session["MyTable"] == null)
{
CreateData(); // first time here - create the data
System.Web.UI.Page.Session["MyTable"] = MyTable; // save the data table
}
else
// we have data - (so this is user change of mind from checkout page)
MyTable = System.Web.UI.Page.Session["MyTable"];
// ok, now load our data into the grid
LoadData(); // load the data
}
else
// this is a post back due to general changes and selections for this
// page under normal and mutliple operations and choices by the user.
// we dont' need to re-display the grid - it persists automatic
// however the datatable variable does NOT persist - so get from session
MyTable = System.Web.UI.Page.Session["MyTable"];
}
public void LoadData()
{
MyTotal = 0;
MyTotalQty = 0;
qtycheck.Value = 0;
GridView1.DataSource = MyTable;
GridView1.DataBind();
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox MyAmount = e.Row.FindControl("Amount");
DataRow MyRow = MyTable.Rows(e.Row.RowIndex);
MyRow("Amount") = MyRow("Qty") * MyRow("Price");
if (MyRow("Purchased") == true)
{
// total up the qty purcchased and the amount
MyTotal += MyRow("Amount");
MyTotalQty += MyRow("Qty");
}
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
// this is our bottom last footer.
e.Row.Cells(3).Text = Strings.FormatCurrency(MyTotal);
e.Row.Cells(2).Text = MyTotalQty;
e.Row.Cells(1).Text = "Totals:";
qtycheck.Value = MyTotalQty; // a hidden control - to check for qty > 0 on checkout
}
}
protected void CheckBox1_CheckedChanged1(object sender, EventArgs e)
{
// user click on purchase a row - udpate totals.
CheckBox cBox = sender;
int RowID = cBox.Attributes("MyRow");
MyTable.Rows(RowID).Item("Purchased") = cBox.Checked;
// data table has been changed - so we call the load data routine to udpate
// our grid
LoadData();
}
protected void Qty_TextChanged(object sender, EventArgs e)
{
// user changed the qry in a row
TextBox tBox = sender;
int RowID = tBox.Attributes("MyRow");
MyTable.Rows(RowID).Item("Qty") = tBox.Text;
// data table has been changed - so we call the load data routine to udpate
// our grid
LoadData();
}
}
Now that is a "bit" of code, but again, not really much.
So, you now get this after running:
So, notice what we do WHEN you check a box!
We simple do this:
protected void CheckBox1_CheckedChanged1(object sender, EventArgs e)
{
// user click on purchase a row - udpate totals.
CheckBox cBox = sender;
int RowID = cBox.Attributes("MyRow");
MyTable.Rows(RowID).Item("Purchased") = cBox.Checked;
// data table has been changed - so we call the load data routine to udpate
// our grid
LoadData();
}
So, now NO MATCHING problem really exists, does it? You click on a row, and we simply change the Purchased setting (a true/false flag). And that is it - done! no matching required. When you thus check a box, we change the table value, and then simply say to the code will you please re-display the data!!! So NOW we are SAVING all that matching work!!!
Now, the check out code becomes a walk in the park.
when you click on the button to check out, we jump to the checkout page.
The markup is now dead simple - since it much the same as the first page - but no ability to change things. Hence this:
<asp:GridView ID="GridView2" runat="server" ShowFooter="true"
Font-Bold="True" Font-Size="Larger" BackColor="#FFCC99"
AutoGenerateColumns="False"
>
<Columns>
<asp:BoundField DataField="Product" HeaderText="Product" Headerstyle-width="250px" />
<asp:BoundField DataField="Price" DataFormatString="{0:C2}" HeaderText="Price" Headerstyle-width="80px" />
<asp:BoundField DataField="Qty" HeaderText="Qty" Headerstyle-width="80px" />
<asp:BoundField DataField="Amount" HeaderText="Amount" Headerstyle-width="80px" />
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
</asp:GridView>
<br />
<asp:Button ID="ChangeOrder_btn" runat="server" PostBackUrl="~/SimpleButton.aspx" Text="Change order"
style="width:140px;height:60px;background-color:#FFCC99;border-radius:25px"
/>
<br />
</div>
And the page looks like:
So, you NOW see why we using a table - since the SAME data now drives both pages, and our problem becomes smaller and smaller - not larger and larger!!
And our code for that checkout page, it is this:
class CheckOut : System.Web.UI.Page
{
private decimal MyTotal = 0;
private int MyTotalQty = 0;
protected void Page_Load(object sender, System.EventArgs e)
{
DataTable MyTable = System.Web.UI.Page.Session["MyTable"];
DataView dv = new DataView(MyTable); // we use data view in palce of data table - it can fitler!!
dv.RowFilter = "Purchased = True";
GridView2.DataSource = dv;
GridView2.DataBind();
}
protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
MyTotal += e.Row.Cells(3).Text;
MyTotalQty += e.Row.Cells(2).Text;
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells(3).Text = Strings.FormatCurrency(MyTotal);
e.Row.Cells(2).Text = MyTotalQty;
e.Row.Cells(1).Text = "Totals:";
}
}
}
So, by build a better design and mouse trap with the first page, and a better approach, then the next page becomes VERY simple, since we re-use the data, re-use the table and in fact darn near re-used the grid too!!!
And to display the order we ONLY have to get the table, and filter the results by purchased.
And the button to go back and change your mind? Well, it just jumps back to the that order page.
So while we did have to build up a bit more "markup" in the first page, we reduced by huge amounts the markup in the 2nd page.
As part of a registration page, users can add their address, if they have not got an address the EmptyItemTemplate within my ListView control commands users to click a button outside of the ListView control to add an address which is shown below;
<asp:Button ID="add_new_address" CssClass="blue" runat="server" Text="Add New Address" OnClick="add_new_address_Click" />
<div id="add_address_div" runat="server">
<asp:DropDownList ID="address_dropdown_insert" runat="server">
<asp:ListItem Value="Home">Home Address</asp:ListItem>
<asp:ListItem Value="Term">Term Time Address</asp:ListItem>
<asp:ListItem Value="Mail">Mail Address</asp:ListItem>
<asp:ListItem Value="Business">Business Address</asp:ListItem>
</asp:DropDownList><br />
Address 1:
<asp:TextBox Text="" runat="server" ID="address_1TextBox" /><br />
Address 2:
<asp:TextBox Text="" runat="server" ID="address_2TextBox" /><br />
Town/City:
<asp:TextBox Text="" runat="server" ID="town_cityTextBox" /><br />
County:
<asp:TextBox Text="" runat="server" ID="countyTextBox" /><br />
PostCode:
<asp:TextBox Text="" runat="server" ID="postcodeTextBox" /><br />
Country:
<asp:TextBox Text="" runat="server" ID="countryTextBox" />
<asp:Button runat="server" CommandName="Insert" Text="Insert" ID="InsertButton" OnClick="insert_address_button_Click" />
<asp:Button runat="server" CommandName="Cancel" Text="Clear" ID="Button4" OnClick="cancel_address_button_Click" /><br />
</div>
I then have the following code behind in C# which inserts the data from the insert form above into a database table;
protected void add_new_address_Click(object sender, EventArgs e)
{
add_address_div.Visible = true;
add_new_address.Visible = false;
}
protected void insert_address_button_Click(object sender, EventArgs e)
{
string userid = Session["user_id"].ToString();
string addtype = address_dropdown_insert.SelectedValue;
string add1 = address_1TextBox.Text;
string add2 = address_2TextBox.Text;
string town = town_cityTextBox.Text;
string county = countyTextBox.Text;
string pcode = postcodeTextBox.Text;
string country = countryTextBox.Text;
string ConnectionString = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(ConnectionString);
myConnection.Open();
String query = "INSERT INTO address (user_id, address_type, address_1, address_2, town_city, county, postcode, country) VALUES (#user_id, #address_type, #address_1, #address_2, #town_city, #county, #postcode, #country)";
SqlCommand myCommand = new SqlCommand(query, myConnection);
myCommand.Parameters.AddWithValue("#user_id", userid);
myCommand.Parameters.AddWithValue("#address_type", addtype);
myCommand.Parameters.AddWithValue("#address_1", add1);
myCommand.Parameters.AddWithValue("#address_2", add2);
myCommand.Parameters.AddWithValue("#town_city", town);
myCommand.Parameters.AddWithValue("#county", county);
myCommand.Parameters.AddWithValue("#postcode", pcode);
myCommand.Parameters.AddWithValue("#country", country);
myCommand.ExecuteNonQuery();
myConnection.Close();
}
protected void cancel_address_button_Click(object sender, EventArgs e)
{
add_address_div.Visible = false;
}
This works, in that data is inserted into the database table as it should but after I click the insert_address_button, the data does not display in the ListView control, it only displays the EmptyItemTemplate. However, if I were to refresh the page the data then appear.
I am also working within View Controls so a normal refresh will bring the user back to the beginning of the registration process and would prefer they would be redirected back to the View control for the Address'.
Is there a step in the process I am missing after the insert so that the data displays in the list view? Any help would be greatly appreciated.
Yes, you need to rebind the ListView's datasource. It's still got the "old" version.
You need the list to update asynchronously from the page when an address is added. You can either have it re-load via Ajax or you can have a javascript function add the address that is being sent to the server side code to the list.
I have a repeater that I populate from a database:
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(#"SELECT CommunityName, CID, Budget FROM Donation WHERE Year = year(getdate()) ORDER BY CommunityName", conn);
conn.Open();
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataSet myDataSet = new DataSet();
adp.Fill(myDataSet);
myRep.ItemDataBound += new RepeaterItemEventHandler(myRep_ItemDataBound);
myRep.DataSource = myDataSet;
myRep.DataBind();
}
void myRep_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var textbox = e.Item.FindControl("community");
textbox.ClientIDMode = ClientIDMode.Static;
textbox.ID = "community" + (e.Item.ItemIndex + 1);
}
Repeater:
<asp:UpdatePanel ID="UpdatePanel" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Repeater ID="myRep" runat="server">
<ItemTemplate>
<div class="form-group">
<asp:Label ID='thisLbl' runat="server" Text='<%# Eval("CommunityName") %>' />
<asp:TextBox runat="server" ID="community" Text='<%# Eval("Budget") %>' CssClass="form-control" />
</div>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
This creates 6 textboxes with labels and values, now my question is how do I detect which of these boxes belongs to the record it was initially pulled from in the database? I want to be able to modify the value in these boxes and hit a button to save them back to the database but I can't seem to wrap my head around getting them to the proper records.
Should I set the ID of the textbox to something I can parse through and match with the proper record? In the ItemDataBound?
You have to put a hidden field inside the repeater item template that takes the value from budget, and another hidden field to keep the CID value that has to be read in the post back request. Of course you need also a button and its click event handler.
<asp:Repeater ID="myRep" runat="server">
<ItemTemplate>
<div class="form-group">
<asp:Label ID='thisLbl' runat="server" Text='<%# Eval("CommunityName") %>' />
<asp:TextBox runat="server" ID="txtBudget" Text='<%# Eval("Budget") %>' CssClass="form-control" />
<asp:HiddenField runat="server" ID="hdOriginalBudget" Value='<%# Eval("Budget") %>' />
<asp:HiddenField runat="server" ID="hdCID" Value='<%# Eval("CID") %>' />
</div>
</ItemTemplate>
</asp:Repeater>
<br />
<asp:Button ID="btn" runat="server" OnClick="btn_Click" />
In your code behind you need to loop inside the repeater to check whether the text box has been changed by comparing its value to the hidden field. After you save the budget value in the database you need to realign the hidden field value to the the new value entered by the user, otherwise you will always save that value after each post back:
protected void btn_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in myRep.Items)
{
var txtBudget = item.FindControl("txtBudget") as TextBox;
var hdOriginalBudget = item.FindControl("hdOriginalBudget") as HiddenField;
var hdCID = item.FindControl("hdCID") as HiddenField;
if (txtBudget.Text != hdOriginalBudget.Value)
{
//If you enter here means the user changed the value of the text box
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(#"UPDATE Donation SET Budget = #Budget WHERE CID = #CID", conn);
cmd.Parameters.Add(new SqlParameter("#Budget", int.Parse(txtBudget.Text)));
cmd.Parameters.Add(new SqlParameter("#CID", int.Parse(hdCID.Value)));
conn.Open();
cmd.ExecuteNonQuery();
}
//After you write in the database realign the values
hdOriginalBudget.Value = txtBudget.Text;
}
}
}
Take care that my code is missing the most basic validation, so if the user writes an invalid value in the textbox (for example "yyy") it breaks. So please don't put it in production as it is!
Hi I am developing one asp.net web application, In that I am creating one registration form. On Registration form page, I have three Dropdownlists named as country, state, city.
So When User selects any country, states in that country will be shown in dropdownlist of state and when user selects state from State dropdownlist He can see lists of cities in in dropdownlist.
I have implemented the functionality, but When User selects value in dropdownlist, post-back occurs.
In my case I don't want to reload the page when User selects country or state, So I have tried to implement the same functionality by using ajax toolkit. But I am not able to achieve the same functionality using ajax.
So in brief my problem is: selecting country, state and city from dropdownlist in asp.net without reloading the page.
Here I am giving you the aspx part.
Please help me.
CountryDropDown
<asp:DropDownList ID="DropDownListCountry" runat="server" Enabled="false"
OnSelectedIndexChanged="DropDownListCountry_OnSelectedIndexChanged"
AutoPostBack ="false">
<asp:ListItem>India</asp:ListItem>
<asp:ListItem>Other</asp:ListItem>
</asp:DropDownList>
StateDropDown
<asp:UpdatePanel ID="UpdatePanel1" runat="server" >
<Triggers>
<asp:AsyncPostBackTrigger ControlID="DropDownListCountry" EventName="OnSelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<asp:DropDownList runat="server" ID="DropDownListState" Enabled="false"
OnSelectedIndexChanged="DropDownListState_OnSelectedIndexChanged">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
wow you manage to make a big mess of explaining whats wrong....
but ill do my best to try to help. first of, first DDL should be defined like so:
<asp:DropDownList ID="Contries" runat="server" AutoPostBack="true" OnSelectedIndexChanged="Contries_SelectedIndexChanged">
<asp:ListItem Text="country1" />
<asp:ListItem Text="country2" />
</asp:DropDownList>
2nd DDL :
<asp:UpdatePanel runat="server" >
<ContentTemplate>
<asp:DropDownList ID="States" runat="server" AutoPostBack="true">
<asp:ListItem Text="state1" />
<asp:ListItem Text="state2" />
</asp:DropDownList>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Contries" EventName="OnSelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
and so on, auto post back must be true in DDL that should do async post back,
try to remove DDLs one by one and start only with 2 then move forward.
First create a web service to retrieve data for your dropdownlists
Create webservice: CascadingDropdown.asmx
in your CascadingDropdown.asmx.cs write code retrieve data for Country, State and City from the database, see this is how i did, you can do something like this, i have used entity framework to fetch the data from the database.
[WebMethod]
public CascadingDropDownNameValue[] FetchCountries()
{
GetLookupResponse countryLookupResponse = commonService.GetLookup("Country");
List<CascadingDropDownNameValue> countries = new List<CascadingDropDownNameValue>();
foreach (var dbCountry in countryLookupResponse.LookupItems)
{
string countryID = dbCountry.ID.ToString();
string countryName = dbCountry.Description.ToString();
countries.Add(new CascadingDropDownNameValue(countryName, countryID));
}
return countries.ToArray();
}
[WebMethod]
public CascadingDropDownNameValue[] FetchStates(string knownCategoryValues)
{
int countryID;
StringDictionary strCountries = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
countryID = Convert.ToInt32(strCountries["Country"]);
GetLookupResponse stateLookupResponse = commonService.GetLookup("State");
List<CascadingDropDownNameValue> states = new List<CascadingDropDownNameValue>();
foreach (var dbState in stateLookupResponse.LookupItems.Where(id => id.DependencyID == countryID))
{
string stateID = dbState.ID.ToString();
string stateName = dbState.Description.ToString();
states.Add(new CascadingDropDownNameValue(stateName, stateID));
}
return states.ToArray();
}
[WebMethod]
public CascadingDropDownNameValue[] FetchCities(string knownCategoryValues)
{
int stateID;
StringDictionary strStates = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
stateID = Convert.ToInt32(strStates["State"]);
GetLookupResponse cityLookupResponse = commonService.GetLookup("City");
List<CascadingDropDownNameValue> cities = new List<CascadingDropDownNameValue>();
foreach (var dbCity in cityLookupResponse.LookupItems.Where(id => id.DependencyID == stateID))
{
string cityID = dbCity.ID.ToString();
string cityName = dbCity.Description.ToString();
cities.Add(new CascadingDropDownNameValue(cityName, cityID));
}
return cities.ToArray();
}
then in your aspx file, you need to register AjaxControlToolkit on top of the page below
, if you haven't installed AjaxControlToolkit, then install it from Nuget packages.
then your dropdownlist code:
<label class="col-sm-3 col-form-label required">Country</label>
<div class="col-sm-9">
<asp:DropDownList ID="ddlCountry" runat="server" CssClass="form-control"></asp:DropDownList>
<ajax:CascadingDropDown ID="csdCountry" runat="server"
Category="Country"
TargetControlID="ddlCountry"
LoadingText="Loading Countries..."
ServiceMethod="FetchCountries"
ServicePath="~/CascadingDropdown.asmx"></ajax:CascadingDropDown>
</div>
<label class="col-sm-3 col-form-label required">State</label>
<div class="col-sm-9">
<asp:DropDownList ID="ddlState" runat="server" CssClass="form-control"></asp:DropDownList>
<ajax:CascadingDropDown ID="csdState" runat="server"
ParentControlID="ddlCountry"
Category="State"
TargetControlID="ddlState"
LoadingText="Loading States..."
ServiceMethod="FetchStates"
ServicePath="~/CascadingDropdown.asmx"></ajax:CascadingDropDown>
</div>
<label class="col-sm-3 col-form-label required">City</label>
<div class="col-sm-9">
<asp:DropDownList ID="ddlCity" runat="server" CssClass="form-control"></asp:DropDownList>
<ajax:CascadingDropDown ID="csdCity" runat="server"
ParentControlID="ddlState"
Category="City"
TargetControlID="ddlCity"
LoadingText="Loading Cities..."
ServiceMethod="FetchCities"
ServicePath="~/CascadingDropdown.asmx"></ajax:CascadingDropDown>
</div>
What i am doing in this is when we select country frop country dropdownlist, I am passing country id to FetchStates webmethod that is in our CascadingDropdown.asmx.cs web service to fetch the states based on country id, and same goes for city, pass state id to FetchCities webmethod to fetch cities.
Hope it helps.