Deleting data from a list - c#

I posted a question 9 days ago but I feel I have more information to add and it would get seen better as a new question. Also I am not allowed to use LINQ so I couldn't use the solution posted
I have a student management tool which allows me to do things such as add, edit and delete students. I have a listbox on the main form which holds studentInfo. I have added the data to the listbox by reading in a CSV containing a column for studentID and a column for studentMark.
I have a class called ModuleData which holds 3 public list structures:
one to hold all the StudentID
one to hold all the StudentMarks
one to hold all the studentInfo(so just the studentID and studentMark but both together.)
My ModuleData class:
namespace Assignment_2_module_marks
{
static class ModuleData
{
public static List<string> studentNumber = new List<string>();
public static List<string> studentMarks = new List<string>();
public static List<string> studentInfo = new List<string>();
}
}
My form_load to populate the listbox on the mainform with some studentinfo:
private void Form1_Load(object sender, EventArgs e)
{
string studentRec; // Declaring string variable
StreamReader inputFile = File.OpenText("COM122.csv");
while (!inputFile.EndOfStream) /
{
studentRec = inputFile.ReadLine();
ModuleData.studentInfo = studentRec.Split(',').ToList();
ModuleData.studentNumber.Add(ModuleData.studentInfo[0]); studentNumber
ModuleData.studentMarks.Add(ModuleData.studentInfo[1]);
lstMarks.Items.Add(ModuleData.studentNumber[0] + " : " + ModuleData.studentInfo[1]);
}
inputFile.Close(); // closes the file
}
I want to be able to click the 'delete' button on the mainform which then opens a new form called deleteRecord. On the delete record form I ask the user for a StudentID and StudentMark. I then want to take those two pieces of data and look through the StudentInfo list and check if any students have the ID and Mark that the user entered in the delete form. If there is a student with the ID and Mark that was entered then I want to delete them from the StudentInfo list and then update the listbox on the mainform so that the student isn't there anymore, if no student is found I want an error to display to tell the user the student doesnt exist
I am not sure how to go about this since I am new to C#
Any help would be appreciated

Here is some psuedo code, I won't write the whole thing for you since this is homework.
var deletedID = -1;
for(int i=0; i< ModuleData.studentInfo.Count; i++)
{
if (ModuleData.studentInfo[i] == studentIDToDelete + " : " + studentMarkToDelete)
{
deletedID = i;
break;
}
}
if (deletedID != -1)
//now remove from lists and reload listbox (hint remove at i)
A much better way to do this would be to have a students class and fill that object with the students and marks. Then you could bind the list of objects directly to the listbox, and use the same list to delete a student.

Knowing this is homework I will try and be more informative rather than providing the answer:
First thing you should do is think of the ModuleData class as a model:
public partial class ModuleData
{
public List<string> studentNumber {get; set;}
public List<string> studentMarks {get; set;}
public List<string> studentInfo {get; set;}
}
You can then populate this model by instantiating it and assigning data to it:
ModuleData entity = new ModuleDate();
entity.studentNumbder = list1;
entity.studentMarks = list2;
entity.studentInfo = list3;
This model will be the object you use to query any datasource and do any CRUD to it.
On Form_Load iterate through the file and get your variables from the comma delimited string. Use this data to populate your ModuleData object and add it to your listbox.
Once you have your ListBox data source populated you can then use user defined parameters to query your ListBox data source and delete it if need be.
heres some psudo code:
foreach(var listItem in lstMarks.Items){
if listItem is parameters then remove from lstMarks
}
I hope this steers you in the right direction.

Related

Cannot display the list of names into the view

I have a list that I prepare in a ViewModel to take values from database table. The list assigned into a model class:
public class DType
{
public string DTName { get; set; }
}
And it get updated by the following method:
public static List<DType> GetDocTypesString(Entity DB, int RKey)
{
return DB.Database.SqlQuery<DType>(#"SELECT * FROM Names
WHERE NK = {0}", RKey).ToList();
}
And then I return the list (model) to the view to list the names into a select menu as the following:
The actual returned model to the view:
public List<DType> ihName { get; set; }
it gets populated by using the method above:
ihName = GetDocTypesString(DB, RKey);
And then, in the view, I use the below:
#Html.Partial("GettingNamesPartial", new ProjName.ViewModels.UploadingPartialViewModel
{
DropdownIHDocType = new SelectList(Model.ihEditorInstanceName)
})
The results are always like this:
Instead to displaying the actual names, the list (select) display:
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
The only thing that matches is the number of items is the same as the names on the database table.
Important Note:
Before trying to pull the names from the database, the list worked just fine by hard coding the names like the following:
DropdownIHDocType = new SelectList(new string[] { "Morgan", "Sam", "Shawn" })
ihName = GetDocTypesString(DB, RKey);
is your culprit. your getting a list of document types, not the variable name from each of those documents. basically your showing the class not its content. you need to get access to the actual document, then find the variable you need and assign that to ihName
so you're grabbing DType not DType.DTname which is what i assume your trying to list

Add new instance of object to list with new values without overwriting old ones using C#

So I've been Googling around for a while and have searched through a number of StackOverflow posts and I must be missing something. I'm doing some XML parsing using C# and I have a series of classes as shown below. In short, the class "Grade" contains a list of of the class "Classroom" and Classroom has a list of "Students" and a list of Teachers.
class Individual
{
public string ID;
public string fName;
public string lName;
public string gradeID;
}
class Classroom
{
public string classID;
public string className;
public string classGrade;
public int numTeachers;
public List<Individual> Students;
public List<Individual> Teachers;
}
class Grade
{
public List<Classroom> Classrooms;
public string classGrade;
}
Essentially, in my program I sift through the XML file and collect a list of students and teachers and add them to my classroom WITHOUT any of them being overwritten. This is because, in a loop, I create a new instance of the class each time the XML node's name is equivalent to "student" or "teacher" because a new node of that type indicates a new individual. You can see that done here:
// node is a student
else if (xmlReader.Name == "student")
{
// create new student object
Individual tempStudent = new Individual();
tempStudent.ID = xmlReader.GetAttribute("id");
tempStudent.fName = xmlReader.GetAttribute("first_name");
tempStudent.lName = xmlReader.GetAttribute("last_name");
tempStudent.gradeID = tempClassroom.classID;
// add student object to classroom list of students
tempClassroom.Students.Add(tempStudent); // classroom class is used inside student and teacher if statements
}
However, I cannot do the same for classroom or grade, since, as you can see above, student and teacher are both dependent on the classroom class for storage purposes. As a result, I cannot figure out how to create a NEW classroom object so that when I do grade.Add(classroom) I can start modifying classroom WITHOUT modifying the already existing nodes within grade. And again, I'd rather not have to write a deep copy function for every time a new classroom is present because that will be incredibly slow.
Edit: sample XML file here:
https://pastebin.com/XzSxgLdb
This code seems to have fixed my problems. When the xmlNodeType was an EndElement I checked the name and then created a new classroom or new grade as necessary. I don't have anymore overwrites so that seems to have cleared things up.
I feel like C# should know that when you add an object to a container that you want that object saved and so C# should create a new reference for a new object. But I guess that isn't the case. Explicitly declaring a new object every time you need one is required.
case XmlNodeType.EndElement:
if (xmlReader.Name == "classroom")
{
// at end of classroom element so add classroom to list
tempClassroom.numTeachers = teacherCounter;
grade.Classrooms.Add(tempClassroom);
if (teacherCounter > highestNumberOfTeachers) // collect the highest number of recorded teachers in a classroom
highestNumberOfTeachers = teacherCounter;
teacherCounter = 0;
tempClassroom = new Classroom();
}
if (xmlReader.Name == "grade")
{
// at end of grade element so prepare for next grade level
Grades.Add(grade);
grade = new Grade();
}

How can I still keep my old sessions after I override them?

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

Remove duplicates entries from the ListView in form c#

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.

issue with Linked 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();

Categories

Resources