I'm creating a product and checkout page. In the product page when a button is pressed I do this
Session["code"] = productLabel.Text;
Session["description"] = descriptionTextBox.Text;
Session["price"] = priceLabel.Text;
Response.Redirect("cart.aspx");
Then in the cart page I have
if ((Session["code"] != null))
{code = (Session["code"]).ToString();}
if ((Session["description"] != null))
{ description = (Session["description"]).ToString(); }
if ((Session["price"] != null))
{price = (Session["price"]).ToString(); }
string item = code + " " + description + " " + price;
cartList.Items.Add(item);
This works, however my problem is when I then add another product to the list, it overrides my first item so theirs only one item in there at a time. How can I keep track of whats currently/previously in there?
Thanks a lot!
You'll probably want to rethink the entire concept and store some custom class instead, one thing you can do is create a list of items in the cart and store that list in the Session.
[Serializable]
public class Item
{
public string Code {get;set;}
public string Description {get;set;}
public string Price {get;set;}
}
List<Item> cart=new List<Item>();
Item item=new Item();
item.Code=productLabel.Text;
item.Description=descriptionTextBox.Text;
item.Price=priceLabel.Text;
cart.Add(item);
Session["cart"]=cart;
//then later pull it out...
List<Item> cart=Session["cart"] as List<Item>; //youll want to check for null etc
//and add another item
Item newItem=new Item();
newItem.Code=productLabel.Text;
newItem.Description=descriptionTextBox.Text;
newItem.Price=priceLabel.Text;
cart.add(newItem);
There's a ton wrong with your architecture. For instance, an enterprising individual could use their browser's tools to change the value in priceLabel.Text and potentially pay less (or nothing!) for their order. But hopefully this gives you an idea about how to proceed.
public class Item
{
public string Code {get;set;}
public string Description {get;set;}
public string Price {get;set;}
}
you can create kind of like a in memory cache to store your items:
public static readonly ConcurrentDictionary<string,List<Item>> myMemoryCache = new ConcurrentDictionary<string,List<Item>>();
and use this as the data source.
You can use the same "key" for multiple entries or you an change this to whatever you like.
Be sure to initialize this in your App_Start
Related
I have a set of code which lists the users details in a list view from a database, it works however multiple entries are often added in when the user clicks to register. How can i get it to work so that the listview knows the name is already present and stops adding mutliple entries into the listview?
this is the code i have for the list view:
listView1.View = View.Details;
var item = new ListViewItem();
item.Text = reader["SSN"].ToString(); // 1st column text
item.SubItems.Add(reader["FirstName"].ToString());// 2nd column text
item.SubItems.Add(reader["LastName"].ToString());// 3rd column text
listView1.Items.Add(item);
You should check manually duplicate entries before adding:
if(!listView1.Items.ContainsKey(stringToInsert))
{
listView1.Items.Add(stringToInsert);
}
If you are loading these from a database you should have a primary key value of sorts, even if it's a mere incremental integer value.
While your ListView can contain ListViewItem populated from your database, it would be wise to store the actual data models themselves in a collection. I would suggest a Dictionary for this, and it would be relatively simple to check for duplicates this way.
For example:
class UserModel
{
public int Id { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then in your Form, you could have a member variable like so:
Dictionary<int, UserModel> users = new Dictionary<int, UserModel>();
void AddItemToList(UserModel model)
{
if(users.ContainsKey(model.Id)) return; // avoid duplicates
var listViewItem = new ListViewItem();
listViewItem.Text = model.SSN;
listViewItem.SubItems.Add(model.FirstName);
listViewItem.SubItems.Add(model.LastName);
listView.Items.Add(listViewItem);
}
In addition, you should be loading your UserModel from the database.
I now have two list box, lstStock and lstSupply. lstSupply consists of
-Pen
-Pencil
-Staple
-Stapler
-Folder
-Notebook
-Eraser
-Marker
and i have two button, one button named btnAdd and another btnRemove.
when i click on btnAdd i want the selected item in lstSupply to be added into lstStock which i have done by
lstStock.Item.Add(lstSupply.SelectedItem);
if i select the same item in lstSupply twice, I want it to be consolidated in lstStock.
for instance, if i select Pen twice, the list box shall give me "Pen x 2" instead of Pen in a line and another Pen in another line.
I got the feeling this is dealing with foreach but i dont really know how to use that.
Okay, so first of all, you're going to need to store something else in lstStock. I'd suggest something like this:
public class StockItem {
public string Name { get; set; }
public int Count { get; set; }
}
Next, I'd suggest that you don't use the .Items field as the actual container where you're storing your stock items. Instead, I'd have a List<StockItem> that you use to populate lstSupply when you refresh.
private List<StockItem> _items = new List<StockItem>();
Then, when you click "add", you do two things:
Iterate through _items to see if there is already a stock item in there of the matching supply. Create one, and add it, if it does not exist.
Find the matching stock item in _items and increment its Count.
To get it to display the way you'd like, we can override ToString() in our StockItem class.:
public class StockItem {
public string Name { get; set; }
public int Count { get; set; }
public override string ToString() {
if (Count > 1)
return Name + " x" + Count;
return Name;
}
}
Finally, whenever any changes are made, you simply re-populate lstStock:
private void RefreshGui() {
lstStock.Items.Clear();
lstStock.Items.AddRange(_items.ToArray());
}
There are plenty of other ways of going about this, but for this simple exercise, this is how I think I would do it.
If you want the code to work without extra coding, you could simply do this:
if (lstSupply.SelectedIndex > -1 && !lstStock.Items.Contains(lstSupply.SelectedItem))
lstStock.Items.Add(lstSupply.SelectedItem);
this way you are sure that you don't add null items and add each item once max.
OK, so I have learned how to create a list, view items in the list, and use the items in the list. I now want to learn how to edit the information that is in the list.
Here is my list:
class ObjectProperties
{
public string ObjectNumber { get; set; }
public string ObjectComments { get; set; }
public string ObjectAddress { get; set; }
}
List<ObjectProperties> Properties = new List<ObjectProperties>();
This is how I am adding values to the list:
ObjectProperties record = new ObjectProperties
{
ObjectNumber = txtObjectNumber.Text,
ObjectComments = txtComments.Text,
ObjectAddress = addressCombined,
};
Properties.Add(record);
I am wanting the user to enter which number they want to update by using a textbox(txtUpdateObjectNumber). I then want to compare that number to the values that are stored in record.ObjectNumber and then if it exist I want to replace the information in record.ObjectNumber and record.ObjectComments where record.ObjectNumber == txtUpdateObjectNumber. If you need me to elaborate on anything just let me know. Any help would be appreciated. Thank You :)
To find the list item, use linq:
ObjectProperties opFound = Properties.Find(x => x.ObjectNumber == txtUpdateObjectNumber.Text);
Or the delegate form:
ObjectProperties opFound = Properties.Find(delegate (ObjectProperties x) { return x.ObjectNumber == txtUpdateObjectNumber.Text; });
Once you've found the item in the list, any changes you make to opFound, including the ObjectNumber, will persist in the list.
i wan to create a linked list that contains the name , age and address of some people , so far i created that code :
LinkedList<string> details = new LinkedList<string>();
details.AddFirst("Name1");
details.AddLast("Name2");
details.AddLast("Name3");
foreach (var display in details)
{
Console.WriteLine(display);
}
ok so now it works fine , but i just input the name , how can i input the age and address , is it like array ? i just don`t know much about linkedlists , and also i tried to delete some nodes of the linkedlist but i failed :
foreach (var item in details)
{
if (item.Contains("Name3"))
{
details.Remove(item);
}
}
but i get that error :
Unhandled Exception: System.InvalidOperationException: Collection was modified after the enumerator was instantiated.
and finally , how can i edit a linkedlist item , like renaming Name2 to Name13 or anything , i would really appreciate any help , just give me idea and i`ll continue digging . Thanks in advance .
You can't remove elements from the list while iterating a list using foreach loop.
if (details.Remove("Name3"))
Console.WriteLine("Removed");
else
Console.WriteLine("Not Found");
A linked list is like an array in that it is a collection of data. Each item in the list stores a link to the next item (and often the previous), hence the name.
You can't modify a list you're looping over, because your reference into the list will then be invalid.
If you wish to add extra information within the list, simply create a class which encapsulates that information, as the LinkedList is a generic type. For example:
//Structure to hold extra information
public class PersonDetails
{
public string Name {get; private set;}
public int Age {get; private set;}
public string Address {get; private set;}
//Constructor
public PersonDetails(string name, int age, string address)
{
this.Name = name;
this.Age = age;
this.Address = address;
}
}
Then you can create a new linked list containing those types:
LinkedList<PersonDetails> list = new LinkedList<PersonDetails>();
list.AddFirst(new PersonDetails("Name", 22, "Address"));
Note that you cannot modify a collection when you are enumerating it, you need to perform your check and modify it outside of your foreach loop.
If you can use LINQ, you can convert your code to a linq approach such as:
details = details.Where(item => !item.Contains("Name3")).ToList();
I have 2 maps that I want to throw into the same source. But it seems one source overrides the second source even though I am targeting different fields.
public class FormViewModel
{
public List<SelectListItem> Items { get; set; }
public string SelectedItem { get; set; }
public string SomeField {get; set;}
// I have many more
}
List<Items> items = Service.GetItems();
FormViewModel viewModel = new FormViewModel()
{
Items = Mapper.Map<List<Items>, List<SelectListItem>>(courses);
};
var fields = Service.GetFields();
viewModel = Mapper.Map<Fields, FormViewModel>(fields);
So now when I do the second map. It will wipe out my first map. How can I stop this?
Edit
I guess I can see why it is happening. I thought it was just filling in those the fields but now I am looking at it and seeing that it is return a new FormViewModel.
I guess I can rearrange my code so that I first do the last map first then add my other map after.
List<CalendarAppointmentReminderVM> vm = Mapper.Map<List<CalendarAppointment>, List<CalendarAppointmentReminderVM>>(taskReminders.Select(x => x.CalendarAppointment).ToList());
Mapper.Map<List<AppointmentReminder>, List<CalendarAppointmentReminderVM>>(taskReminders, vm);
Separately they work. But together the first result gets wiped out by the first one.
pass the output of the first mapping into the second mapping so it doesn't create a new one...
viewModel = Mapper.Map<Fields, FormViewModel>(fields, viewModel);