Fill textbox with text from Listbox - c#

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;

Related

Empty String Textbox.Text inside lambda expression event listener

feel like I'm missing something simple here.
Have a form that looks like this:
public partial class UpdateCustomerForm : Form
{
public UpdateCustomerForm(UpdateCustomer customer)
{
InitializeComponent();
updateCustomerBttn.Click += (sender, e) => HandleID(customer);
}
private void updateCustomerBttn_Click(object sender, EventArgs e)
{
string customerName = nameTb.Text; // This works
this.Close();
}
private void HandleID(UpdateCustomer customer)
{
//all below values are empty
UpdateCustomer customerToUpdate = new UpdateCustomer()
{
CustomerID = customer.CustomerID,
CustomerName = nameTb.Text,
Address1 = addressTb.Text,
Address2 = address2Tb.Text,
Phone = phoneTb.Text,
City = cityTB.Text,
Country = countryTb.Text
};
Customer.UpdateCustomer(customerToUpdate);
CustomerForm CustomerForm = (CustomerForm)Application.OpenForms["CustomerForm"];
CustomerForm.PopulateDGV();
}
}
I don't understand why the .text values of all the textboxes are not represented in the HandleID method. All come in as empty strings. Is there something I need to do to be able to access the values?
Thanks!
For those who have an issue similar to this one:
There are two methods subscribed to the Click event here. The first one is:
updateCustomerBttn.Click += (sender, e) => HandleID(customer);
and the second one is:
private void updateCustomerBttn_Click(object sender, EventArgs e)
which is subscribed in InitializeComponent().
Now, the problem here is that because updateCustomerBttn gets subscribed before HandleID, it also gets executed before HandleID when the event is called. Which means the Form is closed before HandleID gets executed, which is causing the problem.
You can of course change the order in which you subscribe the two methods, but you can already see that this can get really messy over time. So the better option is to move this.Close() to HandleID, or - if you wanna be really clean - add it to the lambda in the constructor:
public partial class UpdateCustomerForm : Form
{
public UpdateCustomerForm(UpdateCustomer customer)
{
InitializeComponent();
updateCustomerBttn.Click += (sender, e) => {
HandleID(customer);
this.Close();
};
}
private void HandleID(UpdateCustomer customer)
{
UpdateCustomer customerToUpdate = new UpdateCustomer()
{
CustomerID = customer.CustomerID,
CustomerName = nameTb.Text,
Address1 = addressTb.Text,
Address2 = address2Tb.Text,
Phone = phoneTb.Text,
City = cityTB.Text,
Country = countryTb.Text
};
Customer.UpdateCustomer(customerToUpdate);
CustomerForm CustomerForm = (CustomerForm)Application.OpenForms["CustomerForm"];
CustomerForm.PopulateDGV();
}
}

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;
}
}

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

List Box with BindingSource containing objects not showing displayName C#

I have found many answered questions on here explaining how to do this when the objects are created as part of the data source but my list box is just displaying "SharePointXMLBuilder.Farm" (Namespace.class) and not the selected DisplayName?
I dont know what I am doing wrong can anyone help please.
I have a list box with a data source as a databinding control and I am adding my created objects(Farm) to the databinding(farmListBindingSource) which all works fine, I just cant get the list to show the property I want it to.
Form: (loads another form takes input and returns to create object from Farm class)
private void CreateNewFarm_Click(object sender, EventArgs e)
{
FarmInput input = new FarmInput();
input.ShowDialog();
Farm nFarm = new Farm();
nFarm.location = input.inputLocation.ToString();
nFarm.identifier = input.inputType.ToString();
nFarm.environment = input.inputEnvironment.ToString();
this.farmListBindingSource.Add(nFarm);
this.testReturnTextBox.Text = nFarm.friendlyName;
}
private void MainForm_Load(object sender, EventArgs e)
{
this.FarmListBox.DisplayMember = "friendlyName";
this.testReturnTextBox.Text = "Form Loaded....";
}
Class:
namespace SharePointXMLBuilder
{
class Farm
{
private string farmLocation;
private string farmIdentifier;
private string farmEnvironment;
private string farmFriendlyName;
//private List<Server> farmServers;
//properties
public string friendlyName
{
get { return farmFriendlyName; }
set { farmFriendlyName = value; }
}
public string location
{
get { return farmLocation;}
set { farmLocation = value; this.buildFriendlyName(); }
}
public string identifier
{
get { return farmIdentifier; }
set { farmIdentifier = value; this.buildFriendlyName(); }
}
public string environment
{
get { return farmEnvironment; }
set { farmEnvironment = value; this.buildFriendlyName(); }
}
//constructor
public Farm()
{
}
//methods
public void AddServer(string s)
{
Server nServer = new Server(s);
// farmServers.Add(nServer);
}
public void buildFriendlyName()
{
this.friendlyName = this.location + " " + this.identifier + " " + this.environment;
}
}
}
Maybe you are not calling this function: buildFriendlyName() for each object in the list prior to binding?
In your buildfriendlyname() method set your private string farmFriendlyName insted of setting the property value friendlyname
Ok, so I tried to manually add DisplayMember in the designer and it wouldn't hold the value, as soon as I removed the DataSource it allowed DisplayMember to be populated so I changed the CreateNewFarm_Click to add the object to farmListBox.Items and when I re-ran the code it was fine.
It appears that you cannot use DisplayMember if you are pulling the objects from a DataSource.

Categories

Resources