C# - Editing Listbox Items - c#

I'm making an app in Windows Forms that simulates a Point of Sales. I'm creating now the part where the user clicks on a product button and it adds to a listbox an item like this: "'Quantity' - 'Name of the product' - 'cost'".
When the button is clicked again is supposed to edit the item like this: "'Quantity+1' - 'Name of the product' - 'cost*2'".
However it just add another item with that information.
So far, my code is the following:
private void bprod1_Click(object sender, EventArgs e)
{
MySqlCommand cmdp1 = new MySqlCommand("SELECT preco_unitario FROM produtos where designacao='" + bprod1.Text + "';", mConn);
mConn.Open();
MySqlDataReader drp1 = cmdp1.ExecuteReader();
drp1.Read();
string getpreco1 = drp1["preco_unitario"].ToString();
mConn.Close();
quant1 = quant1 + 1;
var preco1tot = quant1 * Convert.ToDecimal(getpreco1);
var text1 = quant1.ToString() + " - " + bprod1.Text + " - " + preco1tot.ToString();
listvenda.Items.Add(text1);
}
bprod1 is my button. quant1 starts with value 0. getpreco1 is the value I get from the database (product's cost).
My objective is, when clicked the second time and so on, increase the quantity and add the cost without creating a new item.
I could just delete the item and add another one with the new info, but I want the item to be in the same place as the other, and not on the end of the list.
I appreciate any suggestions and help.
Hope you guys understand what I intend to do.

This line:
listvenda.Items.Add(text1);
is why you're seeing a new item every single time. A mature application would be more likely to use either private class or Model approaches.
Create a new class file within the same namespace and call it something. See below:
public class myProduct
{
public int Quantity {get; set;}
public int Name {get; set;}
public double Price {get; set;}
public myProduct(string name)
{
this.Quantity = 1; this.Name = name; this.Price = 0;
}
public override string ToString()
{
return this.Quantity.ToString() + "-" + this.Name + "-" +
(this.Price * this.Quantity).ToString(c,
CultureInfo.CurrentCulture);
}
}
Now, where you were just adding values, you can check to see if the line exists, and if it does, operate on it. Otherwise, add a new line. Don't bother with ToString() methods and such, as you can actually populate your listbox with a list of the new class! It will call the ToString() method when displaying values.
List<myProduct> listvendaBind = new List<myProduct>();
///insert code here to build your list from the database if you havent already. Otherwise, skip this step so you dont overwrite your list
//now the code for modification
var x = listvendaBind.Where(t => t.Name == newProduct.Name).FirstOrDefault();
if(x.Count() > 0 && (x != null)
listvendaBind[listvendaBind.IndexOf(x[0])].Quantity++;
else
listvendaBind.Add(newProduct);
listvenda.DataSource = listvendaBind;
This is untested, as I'm working on another project at the moment, but should serve as proof of concept.

This is only for learning and I do not recommended using it outside testing environment but you can do something like this:
insetad of
listvenda.Items.Add(text1);
do this:
bool notFound = true;
for(int i=0; i<listvenda.Items.Count; i++)
{
if(((string)listvenda.Items[i]).Contains(" - " + bprod1.Text + " - "))
{
listvenda.Items[i] = text1;
notFound = false;
break;
}
}
if(notFound)
listvenda.Items.Add(text1);
but as I said it should only be temporary solution. Instead of this use CDove solution

Related

Creating a search function in c#, windows form application

I am creating a program as part of a college assignment and must have a database connected to my program. The program is in c# and created in a windows form application with visual studio.
I need to have a text box that allows entry and then a button to search for any values that match that, but I cannot figure out how to read what is inputted, search the database and return them in the text boxes.
I already have the database connected and all of the forms designed and connected together with buttons, however this one part is really baffling me. Any help would be appreciated.P.S I am new to c# and do not fully understand it yet.
Please Take Reference from this link your Answer(along with Database Queries) and Explanation is available
Reference 1
Reference 2
1) Put all the texts from the database in some kind of collection (List for example).
2) Get the text from the textbox by accessing the textbox's Text property. Apply some modifications if you want, such as removing caps, handling keywords etc.
3) Write a linq query that goes something like collection.Where(t => t.Contains(searchString)).ToList(). Alternatively, you can loop over the collection.
4) Feed the resulting list to your output textbox.
In my case, I was used a dataGridView for the DataSet of mysql data and below is the sample code for searchbox.
private void tfSearch_TextChanged(object sender, EventArgs e)
{
if(string.IsNullOrEmpty(tfSearch.Text) == false)
{
dataGridView1.Rows.Clear();
for(int i = 0; i < GlobalState.Items.Tables[0].Rows.Count; i++)
{
string id = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(0).ToString();
string name = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(1).ToString();
string price = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(2).ToString();
string stock = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(3).ToString();
if (name.StartsWith(tfSearch.Text))
{
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = id;
dataGridView1.Rows[index].Cells[1].Value = name;
dataGridView1.Rows[index].Cells[2].Value = price;
dataGridView1.Rows[index].Cells[3].Value = stock;
}
}
}
else if(tfSearch.Text == "")
{
dataGridView1.Rows.Clear();
for (int i = 0; i < GlobalState.Items.Tables[0].Rows.Count; i++)
{
string id = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(0).ToString();
string name = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(1).ToString();
string price = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(2).ToString();
string stock = GlobalState.Items.Tables[0].Rows[i].ItemArray.GetValue(3).ToString();
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = id;
dataGridView1.Rows[index].Cells[1].Value = name;
dataGridView1.Rows[index].Cells[2].Value = price;
dataGridView1.Rows[index].Cells[3].Value = stock;
}
}
Your Welcome.
Get the textbox text when you click on the button then start a query with that search word so youll get back everything what contains that word
Get input text
Textboxname.text;
Query
SELECT * ON table WHERE tagoridorwhatever = textboxname.text
The query part may be a bit different since im weiting this out of my head on a mobile phone

Finding strings using LINQ [duplicate]

This question already has answers here:
Why writing items to console writes only namespace and class name instead of data? [duplicate]
(5 answers)
Closed 5 years ago.
After some research into C# and some test with LINQ with easy examples. I wanted to apply this knowledge into my problem.
My DataStructure as seen from the variable screen (Visual Studio)
- wm
- Nations
- [0]
- Name "USA"
- stockpile
- [0]
- Name "Coal"
- Quantity "quantity"
- Value "value"
- [1] //Same as above
My attempt to access "Coal" has been:
var result = wm.Nations.Find(r => r.Name == "USA")
Console.WriteLine(result + " Result");
But only returns [EconomyTest.NationBuilder] which is an object. How can i extract a string from that object or at least point to USA and access to the stockpile?
Edit1: Data Structure Declaration
//Declarations of Lists
public List<ResourceTemplate> stockpile = new List<ResourceTemplate>();
public List<Money> money = new List<Money>();
public List<PopulationTemplate> population = new
List<PopulationTemplate>();
public NationBuilder(string name)//Constructor
{
this.Name = name;
stockpile = new List<ResourceTemplate>();
money = new List<Money>();
population = new List<PopulationTemplate>();
}
//World Market (Where the actual storage happens)
public WorldMarket()//Constructor
{
//Declaration list
Nations = new List<NationBuilder>();
}
internal List<NationBuilder> Nations {get; set;}
public void AddToWorldMarket(NationBuilder nation)
{
Nations.Add(nation);
}
//Finally how it is managed/used:
WorldMarket wm = new WorldMarket();//Helps with adding those newly
created nations into a List
foreach (string name in NationNames)
{
NationBuilder nation = new NationBuilder(name);//Creates new
Objects nations and used the name provided before
nation.AddResource("Coal", 500, 10);
nation.AddResource("Water", 100, 10);
nation.AddMoney(100);
nation.AddPopulation(1000);
wm.AddToWorldMarket(nation);
Edit2: Function asked in the comments
public void AddResource(string itemName, int quantity, float
value)//Adds Resources to the stockpile
{
stockpile.Add(new ResourceTemplate {Name = itemName, Quantity =
quantity, Value = value });
}
Your entire result variable is just being written out to the console as it is just having its ToString method called to render it, I think what you want is:
Console.WriteLine(result.Name + " Result");
Optionally, if you want the object to show more when rendered to the console, you can override ToString yourself.
public override string ToString()
{
return this.Name + ", stockpile count: " + this.stockpile.Length;
}
Just specify the Name
Console.WriteLine(result.Name + " Result");
To access to stockpile you can iterate it;
foreach (var stock in result.stockpile)
{
//stock.Name
}

Show different objects by double clicking listbox with same name

Currently I'm working on a school project where I have this class members.
The listbox shows the propeties names as in Members.Name.
The problem I have is members with the same name shows the same information in the output textbox. I kinda need a different solution let me paste in my.
public void OutputMember()
{
searchResult = MemberSearch.ByName(Program.memberList, lbmembers.Text);
foreach (Members member in searchResult)
{
tboutput.Text = string.Format("Medlemsnr {0}" +
"Namn: {1}\r\n" +
"Eftername: {2}\r\n" +
"Personnummer: {3}\r\n" +
"Adress: {4}\r\n" +
"Email: {5}\r\n" +
"Tele:{6}\r\n\r\n\r\n",member.MemberNr, member.Name, member.SurName, member.BirthYear.outStringWithId(),
member.Adress, member.Email, member.Tele);
So I understand that the problem of this is the parameters.
I just send a list of members and just the name in text.
public static List<Members> ByName(List<Members> memberList, string member)
{
List<Members> searchList = new List<Members>();
for (int i = 0; i < memberList.Count; i++)
{
if (memberList[i].Name.Equals(member))
{
searchList.Add(memberList[i]);
}
}
return searchList;
so the questions remains how do I view the "right" object in the output textbox by double clicking one of three equal names in the list.
You have not coded what you expect the program to do.
You expect the program to display the related Member based on its position in the list.
But you have coded a search method that returns the Member based on a name match, of which there are possible duplicates.
You are also returning multiple items from the list when you only need 1, and are needlessly looping through all results only to return the last one.
You just need:
public void OutputMember()
{
member = Program.memberList[lbmembers.SelectedIndex]);
tboutput.Text = string.Format("Medlemsnr {0}" +
"Namn: {1}\r\n" +
"Eftername: {2}\r\n" +
"Personnummer: {3}\r\n" +
"Adress: {4}\r\n" +
"Email: {5}\r\n" +
"Tele:{6}\r\n\r\n\r\n",member.MemberNr, member.Name, member.SurName, member.BirthYear.outStringWithId(),
member.Adress, member.Email, member.Tele);
}

How to display data from mysql and display it one by one?

I have a data in mysql and I want to display the data one by one everytime I click the button. How to do it?
string ConnectToServer = #"server=..*.;port=****; user id=sampleID; password=samplePW; database=sampleDB; pooling=false";
public void GetNames()
{
MySqlConnection NameConnector = null;
MySqlDataReader NameReader = null;
try
{
NameConnector = new MySqlConnection(ConnectToServer);
NameConnector.Open();
string Name = "SELECT * from sampleNames";
MySqlCommand NameCommand = new MySqlCommand(Name, NameConnector);
NameReader = NameCommand.ExecuteReader();
while (NameReader.Read())
{
Console.WriteLine(NameReader.GetInt32(0) + ": " + NameReader.GetString(1));
NameLabel.Text += NameReader.GetString("Names") + "\n";
}
}
catch (MySqlException NameException)
{
Console.WriteLine("error : (0)", NameException.ToString());
}
finally
{
if (NameReader != null)
{
NameReader.Close();
}
if (NameConnector != null)
{
NameConnector.Close();
}
}
}
private void ButtonName_Click(object sender, EventArgs e)
{
GetNames();
}
the output:
Name1
Name2
Name3
Name4
Name5
but I wan't is, the Name will appear one by one each time I click the button
like this:
click = output Name1
click = output Name2
click = output Name3
click = output Name4
click = output Name5
There are at least 2 ways of doing that depending on how real-time you need the data and how many DB calls do you want to make. here they are:
Option #1
Initialize a class level variable for names list and an index variable.
List<string> names = null;
int currentNameIndex = 0;
on the click handler, if names is null, populate the names variable with all names in the DB. display the first item as follows.
private void ButtonName_Click(object sender, EventArgs e)
{
if (names == null)
{
names = GetNames();
}
if (currentNameIndex < names.Count)
{
NameLabel.Text += names[currentNameIndex++];
}
}
the getnames need to be modified to return the list of names.
Option #2
Instead of retrieving the whole list in 1 DB call, you could change the SQL query to get the first record from the Table. (based on a Id or some key)
On a click, GetNames will retrieve only 1 record and display that.
On the next click it'll retrieve another record, but not the first ones.
This would typically involve a query involving a key column. Please post your table schema and I can answer with the Query.
an e.g. Query is
int currentNameId = -1; // class level variable.
query is
Select TOP 1 nameId, names from SampleNames Where NameId > currentNameId Order By NameId;
currentNameId = int.Parse(NameReader[nameId].ToString());
the above query assumes that nameId is a unique key and that values start from 0 or greater than -1, and that they are incremental. (identity PKs etc.)
as I mentioned, if you can provide the table structure, we can answer better.
Option #1 is efficient in DB calls but may potentially have stale data.
Option #2 is more chatty but has more real-time data than Option #1.
You are reading all records:
while (NameReader.Read())
If you want to read just one, try put all your connection outside the method and run
NameReader = NameCommand.ExecuteReader();
only once.
Then change
while (NameReader.Read())
to
NameReader.Read()

replacing variable in elements of a List

A more simple example might be:
List <myElement> Elements;
Elements.Add(my1);
Elements.Add(my2);
my1 and my2 eache have a variable of type string named myString
Now I want to change the value of my1.myString. But if I change it the value my2.myString gets changed aswell.
Hopefully it's a bit clearer now
I'm using a List with several Elements within it in C#. The List has as type a self-defined class with several variables in it.
Now I want to change in one list-element the value of a variable. But unfortunately the value gets replaced not only on this but in all elements of this list.
Any advice on how to fix this?
MyProjectElement File1 = this.Project.Elements[0];
MyProjectElement File2 = this.Project.Elements[1];
MyProject my1 = (MyProject)File1;
MyProject my2 = (MyProject)File2;
PageCount_F1 = my1.PageCount;
PageCount_F2 = my2.PageCount;
if (PageCount_F1 != PageCount_F2)
MessageBox.Show("The 2 files need to have the same file length", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
{
my1.IncludeAllPages = false;
my2.IncludeAllPages = false;
for(int i=1; i <= PageCount_F1; i++)
{
StringBuilder value1 = new StringBuilder();
StringBuilder value2 = new StringBuilder();
value1.Append("" + i);
value2.Append("" + (PageCount_F2-i+1));
MyProject my1new = new MyProject();
MyProject my2new = new MyProject();
my1new.Pages = value1.ToString();
my2new.Pages = value2.ToString();
my1.Pages = my1new.Pages;
my2.Pages = my2new.Pages;
this.Project.Elements.Add((myProjectElement)my1);
this.Project.Elements.Add((myProjectElement)my2);
((MyProject)this.Project.Elements[1]).Pages.Remove(0);
((MyProject)this.Project.Elements[i]).Pages.Remove(0);
((MyProject)this.Project.Elements[1]).Pages = "" + 1;
((MyProject)this.Project.Elements[PageCount_F2 - i + 1]).Pages = "" + (PageCount_F2 - i + 1);
((MyProject)this.Project.Elements[i-1]).Pages.Remove(0);
((MyProject)this.Project.Elements[i]).Pages.Remove(0);
((MyProject)this.Project.Elements[i - 1]).Pages = "" + i;
((MyProject)this.Project.Elements[i]).Pages = "" + (PageCount_F2 - i + 1);
}
You need to specify what the condition is to make a change. For example:
myList.ForEach(x => if(whateverCondition) x.myString = "blah" );
But you really need to ascertain what that condition is.
The problem is that in the code that you've put up you're changing your values in a loop that steps through every element and the loop starts indexing the List with index 1, whereas the first element in index 0.
If you're only after changing one element then select that element. Moo-Juice has posted a good suggestion (+1 btw).
p.s. don't post links to external stores with your code, many users that sit behind corporate firewalls can't access them.

Categories

Resources