Retrieve object from an arraylist with a specific element value - c#

I have a class with some attributes. For example class person with name, age, gender and so on as attribute.
People fill out a form, with among other things their gender which is a dropdownlist, they submit it and the person is added to the arraylist.
What I need is a function by clicking a button to display all the persons who chose Female as gender.
Can somebody please help me? I have tried and searched for the right answer for days now and getting a little desperat now.
Many thanks!!!
Olaf
This is my .cs code
public class Person
{
private string name;
private string artistname;
private string address;
private double number;
private double zip;
private string day;
private string gender;
public Person(string name, string artistname, string address, double number, double zip, string day, string gender)
{
this.name = name;
this.artistname = artistname;
this.address = address;
this.number = number;
this.zip = zip;
this.day = day;
this.gender = gender;
}
public override string ToString()
{
string newPerson = name + " aka " + artistname + " lives on " + address + " " + number + " " + zip + " " + day + "Gender: " + gender;
return newPerson;
}
}
And this is my .aspx code:
public partial class Index : System.Web.UI.Page
{
static ArrayList personArrayList;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
personArrayList = new ArrayList();
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
Person p = new Person(txtName.Text, txtArtistName.Text, txtAddress.Text, Convert.ToDouble(txtNumber.Text), Convert.ToDouble(txtPostal.Text), Convert.ToString(dropdownDay.Text), Convert.ToString(dropdownGender.Text));
personArrayList.Add(p);
}
protected void btnShowAll_Click(object sender, EventArgs e)
{
ListBoxShow.Items.Clear();
for (int i = 0; i < personArrayList.Count; i++)
{
ListBoxShow.Items.Add(personArrayList[i].ToString());
}
}
protected void btnShowGentle_Click(object sender, EventArgs e)
{
ListBoxShow.Items.Clear();
}
protected void btnShowLadies_Click(object sender, EventArgs e)
{
ListBoxShow.Items.Clear();
for (int i = 0; i < personArrayList.Count; i++)
{
if (personArrayList[i].gender = "Female")
{
}
}
}
}

The C# way is to take usage of LINQ to query collections, as such:
var persons = personArrayList.AsQueryable();
var females = persons.Where(p => p.gender.Equals("Female"));

I think something like this should do the trick
using System.Linq;
var females = from Person P in personArrayList where P.Gender == "Female" select P;
[Edit]
I had some questions about this myself so asked a question Plain ArrayList Linq c# 2 syntaxes (need a conversion) that can be useful to you.

Do you thank something like that?
protected void btnShowGentle_Click(object sender, EventArgs e)
{
ListBoxShow.Items.Clear();
for (int i = 0; i < personArrayList.Count; i++)
{
if(personArrayList[i].gender == "Male")
ListBoxShow.Items.Add(personArrayList[i].ToString());
}
}
////Possible alternate
//ListBoxShow.Items.Clear();
//ListBoxShow.Items.AddRange(personArrayList.Where( x => x.gender == "Male"));

Related

How to show all values from a class in a textbox from a combobox

I am currently creating a winform program where account holders are able to purchase specific products/services.
The current problem I am having is that when I select an account holders name on the combobox, all the account holders details is supposed to be shown on the multiline textbox, however all im getting so far is the account holders name.
Here is the relevant code...
public Form1()
{
InitializeComponent();
mAccHolder[0] = new Customer("Rich", "Bronze Account", 11);
mAccHolder[1] = new Customer("Patrick", "Silver Account", 21);
mAccHolder[2] = new Customer("Steve", "Gold Account", 12);
mAccHolder[3] = new Customer("Kevin", "Platinum Account", 25);
foreach(Customer r in mAccHolder)
{
comboBox1.Items.Add(r.GetName());
}
}
and the code which connects the combobox and textbox together...
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == -1)
{
cstTxtBox.Text = string.Empty;
}
else
{
cstTxtBox.Text = comboBox1.SelectedItem.ToString();
}
You are only getting the account holders name because that is all you are giving the combobox. It does not know anything about a Customer. It only knows that it was supplied a string value, and that is all. You can pass it the name, this is fine, but you need to print the information corresponding with what that combobox item represent. You can do this by using an index. Since we know they are being supplied in the combobox in order, the index's will match. However, unless you override the ToString, you are just going to get the object name, e.g. "Customer.Object[]".
I threw an example together for you.
private Customer[] customers = new Customer[3];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
customers[0] = new Customer("Bob", "Bronze", 22);
customers[1] = new Customer("Jane", "Silver", 32);
customers[2] = new Customer("Jordan", "Gold", 26);
foreach(var cust in customers)
{
comboBox1.Items.Add(cust.Name);
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Text = customers[comboBox1.SelectedIndex].ToString();
}
Also, in your 'Customer' class you may want to override the "ToString()" to make this nicer.
public override string ToString()
{
return Name + "\r\n" + Membership + "\r\n" + Age;
}
Using your example with an array of “Customer” objects, when the combo box's selected value changes, you need to get the selected “Customer” Object from the array mAccHolder. Once you have this customer either you can output the “Customer” values individually to the text box or you could make a “ToString” method for the “Customer” to output the customer info to your specifications, which is what the code below does.
The changes below to your current code appear to work as described. I added a blank value to the combo box so the user can de-select any currently selected customer. The “GetCustomer” method simply loops through the array mAccHolder to get the selected customer in the combo box. Hope this helps.
Customer Class
class Customer {
public string Name { get; set; }
public string AccountType { get; set; }
public int ID { get; set; }
public Customer(string inName, string actType, int inID) {
Name = inName;
AccountType = actType;
ID = inID;
}
public string GetName() {
return Name;
}
public override string ToString() {
return "Name: " + Name + " AccountType: " + AccountType + " ID: " + ID;
}
}
Updated code to use the Customer Class above.
Customer[] mAccHolder = new Customer[10];
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
mAccHolder[0] = new Customer("Rich", "Bronze Account", 11);
mAccHolder[1] = new Customer("Patrick", "Silver Account", 21);
mAccHolder[2] = new Customer("Steve", "Gold Account", 12);
mAccHolder[3] = new Customer("Kevin", "Platinum Account", 25);
comboBox1.Items.Add(""); // <- add a blank selection so the user can select NO customer
foreach (Customer r in mAccHolder) {
comboBox1.Items.Add(r.GetName());
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
if (comboBox1.SelectedIndex == -1) {
cstTxtBox.Text = string.Empty;
} else {
if (comboBox1.SelectedItem.ToString() != "") {
Customer selectedCustomer = GetCustomer(comboBox1.SelectedItem.ToString());
if (selectedCustomer != null)
cstTxtBox.Text = selectedCustomer.ToString();
else
cstTxtBox.Text = "Customer not found!";
}
else {
cstTxtBox.Text = "No Customer selected";
}
}
}
private Customer GetCustomer(string targetName) {
foreach (Customer curCustomer in mAccHolder) {
if (curCustomer.Name.Equals(targetName)) {
return curCustomer;
}
}
return null;
}
Easy add directly Customer to combobox. With this way you can use it anywhere any time. like this.
public Form1()
{
InitializeComponent();
mAccHolder[0] = new Customer("Rich", "Bronze Account", 11);
mAccHolder[1] = new Customer("Patrick", "Silver Account", 21);
mAccHolder[2] = new Customer("Steve", "Gold Account", 12);
mAccHolder[3] = new Customer("Kevin", "Platinum Account", 25);
foreach(Customer r in mAccHolder)
{
ComboboxItem item = new ComboboxItem();
item.Text = r.GetName();
item.Value = r;
comboBox1.Items.Add(item);
}
}
And use Customer where you want...
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == -1)
{
cstTxtBox.Text = string.Empty;
}
else
{
Customer c=(Customer) comboBox1.SelectedValue;
cstTxtBox.Text = c.whatyouwant....
}
You can use foreach,
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == -1)
{
cstTxtBox.Text = string.Empty;
}
else
{
foreach (var item in comboBox1.Items)
{
cstTxtBox.Text = cstTxtBox.Text + item.ToString();
}
}
}

C# - Search for Substring from User Input

I wish to add a search function to my application, I've seen many examples however, all of the data is added by the programmer. How would I implement a search function where the parameters/values aren't pre-defined. I'm guessing I'd have to create another instance of a List<> as I'm already using one?
public Form1()
{
InitializeComponent();
}
List<Book> books = new List<Book>();
private void Form1_Load(object sender, EventArgs e)
{
}
//Settng Values
public void button1_Click(object sender, EventArgs e)
{
Book b = new Book();
b.Title = textBox1.Text;
b.ISBN = textBox2.Text;
b.Onloan = trueCheckBox.Checked;
listView1.Items.Add(b.Title + ", " + b.ISBN + ", " + b.Onloan);
books.Add(b);
textBox1.Text = null;
textBox2.Text = null;
}
//Method to check if item is aviable or note - boolean type
void avaiable()
{
if (trueCheckBox.Checked = true)
{
bool onloan = true;
}
else
{
bool onloan = false;
}
}
private void button2_Click(object sender, EventArgs e)
{
Remove();
}
//Remove item from both the List & Listview
void Remove()
{
try
{
listView1.Items.Remove(listView1.SelectedItems[0]);
books.RemoveAt(listView1.SelectedItems[0].Index);
}
catch
{
}
}
//Display information within their field when selected an item is selected
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
else
{
textBox1.Text = books[listView1.SelectedItems[0].Index].Title;
textBox2.Text = books[listView1.SelectedItems[0].Index].ISBN;
trueCheckBox.Checked = books[listView1.SelectedItems[0].Index].Onloan;
}
}
//Update the values without having to re-add
private void button3_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
else
{
books[listView1.SelectedItems[0].Index].Title = textBox1.Text;
books[listView1.SelectedItems[0].Index].ISBN = textBox2.Text;
books[listView1.SelectedItems[0].Index].Onloan = trueCheckBox.Checked;
listView1.SelectedItems[0].Text = textBox1.Text + ", " + textBox2.Text + ", "+ trueCheckBox.Checked;
}
}
private void searchBox_TextChanged(object sender, EventArgs e)
{
//Here's where I am stuck, I've added a textField and labelled it search box
}
}
//Class - set & get methods
class Book
{
public string isbn;
public string title;
private Boolean onloan;
public Book()
{
this.isbn = isbn;
this.title = title;
}
public string ISBN
{
get { return isbn; }
set { isbn = value; }
}
public string Title
{
get { return title; }
set { title = value; }
}
public Boolean Onloan
{
get { return onloan; }
set { onloan = value; }
}
}
}
Thank you.
EDIT-
Essentially, the search function should allow the user to search for a book using just a substring i.e. "Mars" should return a the book with the title "The Programmer From Mars" < (Just an example). I'm guessing I'd have to use the .Contain method?
Correct, you will need to use the "Contains" method. Note that "Contains" is case sensitive so you would need to cater for that.
So you would have something like:
var textToSearch = searchBox.Text.ToLower();
var foundBooks = books.Where(book => book.Title.ToLower().Contains(textToSearch)).ToList();
Assuming books is the list of books to search from:
List<Book> searchResult = books.Where(b => b.Title.Contains(searchTerm)).ToList();
This would return a list of books where the input string is found in the title.
You can do exact matching with b.Title == searchTerm, and similar with the other properties of Book.
The syntax above is LINQ and can be a little confusing at first, but works very well for things like this.
Edit:
To use this, you'll want using System.Linq;
Since your search seems to be on TextChanged, you'd want to put this code in your searchBox_TextChanged() method:
This gets the textbox the user is typing into:
TextBox searchTerm = sender as TextBox;
And this filters your list of books by the current search:
List<Book> searchResult = books.Where(b => b.Title.Contains(searchTerm.Text)).ToList();
Note as in the other answer you may want to do ToLower() (or upper) to make searches case-insensitive.
All that's left to do now is display the filtered result searchResult back to the user.
Managed to do it, this is my code and it works. If anyone wants to use it for future reference here it is.
private void button4_Click(object sender, EventArgs e)
{
listView1.SelectedItems.Clear();
for (int i = listView1.Items.Count -1; i >= 0; i--)
{
if (listView1.Items[i].ToString().ToLower().Contains(searchBox.Text.ToLower())) {
listView1.Items[i].Selected = true;
}
}

Fill textbox with text from Listbox

I have looked at many answers on this topic but have found no solution because my particular situation uses a class called Customer and I am trying to set my textbox called tbxFirstName to the selected name I click on in the listbox by setting the tbxFirstName.Text = cust.getFirstName;.
I can not figure out why it is not re-filling the first name text box with the string in the selected item.
This is my code.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listBoxDatabase.Name = "CUSTOMERS";
}
private void btnAddCustomer_MouseClick(object sender, MouseEventArgs e)
{
Customer cust = new Customer(tbxFirstName.Text, tbxLastName.Text, tbxPhone.Text);
if (listBoxDatabase.Items.Contains(cust.ToString()))
{
MessageBox.Show("Customer Already Exist!", "ERROR");
} else
{
listBoxDatabase.Items.Add(cust.ToString());
}
}
private void listBoxDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
Customer cust = new Customer(tbxFirstName.Text, tbxLastName.Text, tbxPhone.Text);
tbxFirstName.Text = cust.getFirstName;
}
}
class Customer
{
//Variables
private string firstName, lastName, phone;
//Constructor
public Customer(string firstName, string lastName, string phone)
{
this.firstName = firstName;
this.lastName = lastName;
this.phone = phone;
}
public string getFirstName
{
get
{
return firstName;
}
}
public string getLastName
{
get
{
return lastName;
}
}
public string getPhone
{
get
{
return phone;
}
}
public override string ToString()
{
return firstName + " " + lastName + " " + phone;
}
}
Can anyone help me with what I am missing?
Your problems are caused by the fact that you store a string in your ListBox items. Instead you should store a Customer instance and retrieve a Customer instance
Your Customer class contains the override of ToString, so the ListBox calls itself this override when it needs to display the item, but the underlying dataobject stored by the ListBox is a full Customer object
private void btnAddCustomer_MouseClick(object sender, EventArgs e)
{
Customer cust = new Customer(tbxFirstName.Text, tbxLastName.Text, tbxPhone.Text);
// This will replace the Contains because now you have
// a collection of Customer not a collection of strings.
if (listBoxDatabase.Items.Cast<Customer>()
.Any(x => x.ToString() == cust.ToString()))
{
MessageBox.Show("Customer Already Exist!", "ERROR");
}
else
{
// Add a customer, not its ToString representation
listBoxDatabase.Items.Add(cust);
}
}
Now, you can retrieve the Customer instance directly with
private void listBoxDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBoxDatabase.SelectedIndex != -1)
{
Customer cust = listBoxDatabase.Items[listBoxDatabase.SelectedIndex] as Customer;
tbxFirstName.Text = cust.getFirstName;
tbxLastName.Text = cust.getLastName;
tbxPhone.Text = cust.getPhone;
}
}
Well it's not changing cause it's the same text as can be seen below. You are creating Customer object with data from tbxFirstName.Text and that's itself you are trying to re-populate in the same textbox.
Customer cust = new Customer(tbxFirstName.Text, tbxLastName.Text, tbxPhone.Text);
tbxFirstName.Text = cust.getFirstName;
Per your comment, you want to fill textbox with listbox selected item text. In that case you can just do like
private void listBoxDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
tbxFirstName.Text = listBoxDatabase.SelectedItem.ToString();
}
From your original code posted you are creating a NEW customer each time the selection changes. But you want to be selecting the customer object that is highlighted in the listbox - not making a brand new one.
EDIT: I also noticed that when you add to the listbox you are adding a string, not the object. If you want to do it that way then you would need to parse the string and break it up by the spaces or something. I would suggest adding the item/object to the listbox instead
In your SelectedIndexChanged event try something like this
Customer c = (Customer)listboxDatabase.SelectedItem;
tbxFirstName.Text = c.FirstName;
tbxLastName.Text = c.LastName;
tbxPhoneNumber.Text = c.PhoneNumber;

Is there a way to assign values to a combobox without using a datasource?

I'm using Entity Framework to throw together a combobox with values from my MSSQL database using the following
using (var context = new Entity())
{
var things = (from p in context.Stuff
where ((p.SourceId == StuffId && p.Domain.Value == "Stuff")
|| (p.SourceId == OtherStuffId && p.Domain.Value == "OtherStuff"))
&& p.Done == true orderby p.StuffId
select p);
foreach(var stuff in things)
cboRejectTask.Items.Add(stuff.StuffId + ": " + stuff.StuffType.Description + " " + stuff.StuffType.DisplayName);
}
I'd like to assign values to each row so that when it comes time to grab what the user selected I don't have to do string manipulation to get what I want. I don't want to use a datasource if possible.
Solution:
Given there isn't a better way to do this than creating a custom class I went ahead and did so using the selected answer's code modified a bit for long-term use. (note: you could really use any given object as long as ToString() returned the "display text" and it had a Tag or any writeable property compatible with your needs)
public class ComboBoxItem
{
public string Display;
public object Value;
public override string ToString()
{
return Display;
}
}
Given this code I can now change my code to the following:
using (var context = new Entity())
{
var things = (from p in context.Stuff
where ((p.SourceId == StuffId && p.Domain.Value == "Stuff")
|| (p.SourceId == OtherStuffId && p.Domain.Value == "OtherStuff"))
&& p.Done == true orderby p.StuffId
select p);
foreach(var stuff in things)
cboRejectTask.Items.Add(new ComboBoxItem() { Display = stuff.StuffId + ": " + stuff.StuffType.Description + " " + stuff.StuffType.DisplayName, Value = stuff.StuffId });
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var cbi1 = new ComboBoxItem("Item 1") { Id = 1 };
var cbi2 = new ComboBoxItem("Item 2") { Id = 2 };
var cbi3 = new ComboBoxItem("Item 3") { Id = 3 };
comboBox1.Items.Add(cbi1);
comboBox1.Items.Add(cbi2);
comboBox1.Items.Add(cbi3);
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var id = ((ComboBoxItem)comboBox1.SelectedItem).Id;
MessageBox.Show(id.ToString());
}
}
public class ComboBoxItem
{
private readonly string text;
public int Id { get; set; }
public ComboBoxItem(string text)
{
this.text = text;
}
public override string ToString()
{
return text;
}
}
I think you might find this usefull:
comboBox1.Items.Add(1);
comboBox1.Items.Add(2);
comboBox1.Items.Add(3);
private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
{
//this will set what gets displayed in the combobox, but does not change the value.
e.Value = "display value";
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show((sender as ComboBox).SelectedItem.ToString());
}

error operators == cannot be applied search array?

this probably will be confusing or messy but I need help with my program
this is my program:
public partial class Form1 : Form
{
int itemCountInteger;
public struct Patient
{
public string patientidstring;
public string firstNameString;
public string lastNameString;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public class Patientn
{
private int patientId;
public string firstName;
private string lastName;
public Patientn()
{
patientId = 0;
firstName = "";
lastName = "";
}
public Patientn(int idValue, string firstNameVal, string lastNameVal)
{
patientId = idValue;
firstName = firstNameVal;
lastName = lastNameVal;
}
}
I want to be able to use a patient class instead of a struct to add patients and for the search code bellow I get the error "operators == cannot be applied" i want to be able to search the array if the text in textbox matches a name in array if so display surname help?
//Array
Patient[] patientInfo = new Patient[10];
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (Patient patientinfoIndex in patientInfo)
patientInfo[itemCountInteger].patientidstring = textBox1.Text;
patientInfo[itemCountInteger].firstNameString = textBox2.Text;
patientInfo[itemCountInteger].lastNameString = textBox3.Text;
string names = patientInfo[itemCountInteger].firstNameString + " " + patientInfo[itemCountInteger].lastNameString;
listBox1.Items.Add(names);
itemCountInteger++;
listBox1.SelectedItem = names;
}
catch
{
MessageBox.Show("Contacts are limited to 20. Please delete some contacts prior to adding more.");
}
}
//Search Button search a patients name and display his surname in the label if patient is found display his surname
private void button2_Click(object sender, EventArgs e)
{
int intTest = 0;
for (int x = 0; x < patientInfo.Length; x++)
{
if (textBox4.Text == patientInfo[x])
{
label6.Text =("surname");
intTest = 1;
}
}
if (intTest == 0)
{
label6.Text = ("not found");
}
}
I'm new to all of this sorry for asking and thanks in advance if you can help me with anything.
You're getting the error because of this line; textBox4.Text == patientInfo[x]. There are a few problems here but firstly, textBox4.Text is a string and you're trying to do an equality comparison with a Patient the compiler is saying there is no == operator defined for that. You can overload the == operator for Patient but this would only allow you to compare one instance of type Patient to another, never will you be able to compare a Patient to a string unless you cast both to type object in which case it's just going to do a reference comparison (not what you want).
I'm not sure which property in Patient you want to use here but I do know you need to compare textBox4.Text to one of the strings within the Patient class. Something like this would work; (textBox4.Text == patientInfo[x].lastName)
It makes no sense to compare System.String--the type returned by textBox4.Text--to a Patientn instance. You probably mean to compare Text to patientInfo[x].lastNameString.
You can't do
textBox4.Text == patientInfo[x]
patientInfo contains instances of Patience and textBox4.Textis a string. There is no possible comparison between those two and that's why you get the error.
You're probably trying to do something like this
textBox4.Text == patientInfo[x].patientidstring

Categories

Resources