ToString override to return array - c#

I wanted to make a wpf program that when you click the Generate button the class SSales will get/store the arrays of values to the class then return it to the listbox. New here. Sorry.
private void GenerateButton_Click(object sender, EventArgs e)
{
Random rand = new Random();
int[] year = { 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 };
double[] Sales = new double[10];
for (int i = 0; i < 10; i++)
{
Sales[i] = rand.Next(1000, 50000);
}
SSales yearSale = new SSales(year, Sales);
for (int j = 0; j < 10; j++){
//I want the listbox to display the values of yearSale.Year and yearSale.Sales
listBox1.Items.Add(yearSale);
}
}
public class SSales
{
public int[] Year { get; set; }
public double[] Sales { get; set; }
public SSales(int[] iYear, double[] dSales)
{
Year = iYear;
Sales = dSales;
}
public override string ToString()
{
//I'm trying to make this format "2001 $25,000.00" then return it to listbox
return string.Format("{0}\t\t{1:C0}", Year, Sales);
}
}

Since you are adding 10 SSales objects to the ListBox, each object should accept a single int and a single double:
public class SSales
{
public int Year { get; set; }
public double Sales { get; set; }
public SSales(int iYear, double dSales)
{
Year = iYear;
Sales = dSales;
}
public override string ToString()
{
return string.Format("{0}\t\t{1:C0}", Year, Sales);
}
}
Try this:
private void GenerateButton_Click(object sender, EventArgs e)
{
Random rand = new Random();
int[] year = { 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 };
double[] Sales = new double[10];
for (int i = 0; i < 10; i++)
{
Sales[i] = rand.Next(1000, 50000);
}
for (int j = 0; j < 10; j++)
{
listBox1.Items.Add(new SSales(year[j], Sales[j]));
}
}

That's not how you use ToString - it isn't supposed to return an array.
Instead, you should create a function on SSales that takes a parameter, and that would give you the formatted result of the sale you want. Something like this:
public string GetFormattedSale(int s) {
string.Format("{0}\t\t{1:C0}", Year[s] , Sales[s]);
}
You could then call this from your button click code like this:
listBox1.Items.Add(yearSale.GetFirmattedSale(j));
If you really must use ToString, the you need to make another class that contains the data for a single sale, not all 10 sales. You can then implement ToString on just that single sale.

Related

How do I get the sum or total of the prices of items inside my list box?

The button 1-10 are the items;
the pos screenshot
codes i used but doesn't work maybe it's wrong but i can't find answers on the internet
private void enterPayment_Click(object sender, EventArgs e)
{
label1.Text = "Payment";
//price.ReadOnly = false;
//price.Text = "0.00";
//price.Focus();
//Kukunin ko yung total ng List Items
double total = 0;
int ilan = orders.Items.Count;
for (int i = 0; i >= ilan; i++)
{
string item = orders.Items[i].ToString();
int Index = item.IndexOf("#");
int Length = item.Length;
string presyoString = item.Substring(Index + 1, Length - Index - 1);
double presyoDouble = double.Parse(presyoString);
total += presyoDouble;
//price.Text = (total + ".00");
}
price.Text = (total + ".00");
}
I strongly recommend that you use the listbox as a view only, not to be use to perform the mathematical operation. The data can be use in collection such as List so that you can perform better operation.
For example, at program load, I will add product information on List<T> and on form, I place a tag in the button consider it as product Id. So, when I click on the button, it will pass the tag property and from there, I will search the product information on list regarding my Id and add into another final List<T> and get the sum of it.
public partial class Form1 : Form
{
private List<ProductDisplay> listProductDisplay = new List<ProductDisplay>();
private List<ProductInformation> listProductInfo = new List<ProductInformation>();
public Form1()
{
InitializeComponent();
LoadProduct();
}
private void LoadProduct()
{
listProductDisplay = new List<ProductDisplay>()
{
new ProductDisplay{ProdID = 1,ProdName = "Chargrilled Burger",ProdPrice = 330.00m},
new ProductDisplay{ProdID = 2,ProdName = "Mushroom N' Swish",ProdPrice = 330.00m},
new ProductDisplay{ProdID = 3,ProdName = "Chicken Burger",ProdPrice = 250.00m},
new ProductDisplay{ProdID = 4,ProdName = "Steak Loader",ProdPrice = 220.00m},
new ProductDisplay{ProdID = 5,ProdName = "Cookie Sandwich",ProdPrice = 125.00m},
new ProductDisplay{ProdID = 6,ProdName = "Cookie Sundae",ProdPrice = 175.00m},
new ProductDisplay{ProdID = 7,ProdName = "Chicken Nuggets",ProdPrice = 145.00m},
new ProductDisplay{ProdID = 8,ProdName = "Curly Fries",ProdPrice = 75.00m},
new ProductDisplay{ProdID = 9,ProdName = "Sprite",ProdPrice = 50.00m},
new ProductDisplay{ProdID = 10,ProdName = "Coke",ProdPrice = 50.00m}
};
}
private void InsertOrder_ButtonClick(object sender, EventArgs e)
{
try
{
Button btn = (Button)sender;
int number = Convert.ToInt32(btn.Tag);
var itemProduct = listProductDisplay.First(x => x.ProdID == number);
ProductInformation prod = new ProductInformation
{
ProdID = itemProduct.ProdID,
ProdName = itemProduct.ProdName,
ProdPrice = itemProduct.ProdPrice,
ProdQty = 1
};
prod.ProdDisplayName = $"{prod.ProdQty}x {prod.ProdName} #{prod.ProdPrice.ToString("F")} = {(prod.ProdPrice * prod.ProdQty).ToString("F")}";
listProductInfo.Add(prod);
listBoxItem.DataSource = null;
listBoxItem.DataSource = listProductInfo;
listBoxItem.DisplayMember = "ProdDisplayName";
listBoxItem.ValueMember = "ProdID";
var price = listProductInfo.Sum(t => (t.ProdPrice * t.ProdQty));
txtPayment.Text = price.ToString("F");
}
catch (Exception ex)
{
MessageBox.Show("Failed to insert order");
throw;
}
}
}
public class ProductDisplay
{
public int ProdID { get; set; }
public string ProdName { get; set; }
public decimal ProdPrice { get; set; }
}
public class ProductInformation
{
public int ProdID { get; set; }
public string ProdName { get; set; }
public string ProdDisplayName { get; set; }
public decimal ProdPrice { get; set; }
public int ProdQty { get; set; }
}
Parsing and extracting values from a string like that is very error prone and brittle. What happens if the order of fields in your line changes? Or if you add currency symbols?
#Luiey's solution is the smartest way to go ahead. But if for some reason you cannot make so many changes to your code, the bare minimum you want to do is store the items in a list as a custom object with statically typed fields for price, quantity and total. The ListBox class invokes a ToString() at the time of rendering items. So you can easily override this method to prepare the output string according to your needs.
private class LineItem
{
public LineItem()
{
Quantity = 0;
Description = string.Empty;
Price = 0;
}
public int Quantity
{
get;
set;
}
public string Description
{
get;
set;
}
public int Price
{
get;
set;
}
public int Total
{
get
{
return Quantity * Price;
}
}
public override string ToString()
{
return $"{Quantity} × {Description} # {Price} = {Total}";
}
}
Then you add an item to your ListBox like this.
var item = new LineItem()
{
Quantity = 1,
Description = "Foo bar",
Price = 10
};
listBox1.Items.Add(item);
And add them up like this.
var items = listBox1.Items.Cast<LineItem>().ToArray();
var accumulator = 0;
accumulator = items.Aggregate(accumulator, (a, i) => a + (i.Quantity * i.Price), (a) => a);

How to send some list to another class and how to connect it

Im doing my HW to school, making some game.. i took blackjack bcs i thought its easy, but now i know that isnt easy for me.. So i need help with solution.
I tried to connect somehow the lists "cards", but idk if it is connected or not.
Here is shuffle
public class Shuffle
{
public List<Card>cards;
public void Michani()
{
Random ran = new Random();
int r = cards.Count;
while (r > 1)
{
int n = ran.Next();
Card card = cards[n];
cards[n] = cards[r];
cards[r] = card;
}
}
}
public class Card
{
public CardValue Value { get; set; }
public CardSuit Suit { get; set; }
public int Weight { get; set; }
}
public enum CardValue : int
{
Eso = 1,
Dvojka = 2,
Trojka = 3,
Ctyrka = 4,
Petka = 5,
Sestka = 6,
Sedmicka = 7,
Osmicka = 8,
Devitka = 9,
Desitka = 10,
Jack = 11,
Queen = 12,
King = 13,
}
public enum CardSuit : int
{
Hearts = 1,
Spades = 2,
Clubs = 3,
Diamons = 4
}
Here is ending card:
public class DeckGen
{
public List<Card> cards;
public void Deck()
{
for (int v = 0; v < 13; v++)
{
for (int s = 0; s < 4; s++)
{
cards.Add(new Card() { Suit = (CardSuit)s, Value = (CardValue)v });
if (s <= 8)
{
cards[cards.Count - 1].Weight = s + 1;
}
else
{
cards[cards.Count - 1].Weight = 10;
}
};
}
}
}
Here is creating the deck:
public class DrawCard
{
public List<Card> cards { get; }
public Card Lizani()
{
if (cards.Count <= 0)
{
DeckGen();
Shuffle();
}
Card returnedcard = cards[cards.Count - 1];
cards.RemoveAt(cards.Count - 1);
return returnedcard;
}
public void Shuffle()
{
}
public void DeckGen()
{
}
}
Here is drawing a card:
There is a bunch of problems here, and a blog worthy of the best way to do this. But may i suggest and old fashioned (debatable) approach of just using and extension method
Note i fixed bunch of mistakes
public static class CardUtils
{
private static Random ran = new Random();
public static void Shuffle(this List<Card> cards)
{
var n = cards.Count;
while (n > 1)
{
n--;
var k = ran.Next(n + 1);
Card value = cards[k];
cards[k] = cards[n];
cards[n] = value;
}
}
}
Usage
chards.Shuffle();
Note i say old fashioned as we tend not to use static classes like this these days for test-ability , and DI service. However, i think this is a nice simple solution and accessible everywhere you need it
Also Note There are better randomization techniques, your players might get angsty because the shuffler isn't working that good
I don't know I did get the question truely or not but I think making the class and list static will do the trick and then you can call the list like
DeckGen.CardList;

Is it possible to get the item index using Contains?

When I use if (moscowCars.Contains(cars[x].Name)) it founds the value in a collection and I believe that not necessary to use moscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name))); to find it for a second time, just: moscowCars.Remove(cars[x].Name);. Of course, I can use try & catch instead of if, but I just want to know can I get the item index using Contains?
using System.Collections.Generic;
namespace Autoworld
{
class GoodCars
{
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name)));
}
}
}
}
}
You could remove the two-step process entirely and just use .Remove which will return:
true if item is successfully removed; otherwise, false. This method
also returns false if itemwas not found in the List.
This would then look like:
for (int x = 0; x < cars.Count; x++)
{
moscowCars.Remove(cars[x].Name);
}
And if you need to handle the case where no car is found to be removed, you can wrap that call in an if condition like:
for (int x = 0; x < cars.Count; x++)
{
if (!moscowCars.Remove(cars[x].Name))
{
// Handle no cars to remove
}
}
Worth noting that behind the scenes, .Remove ultimately just gets the index and then removes the item at that index (which is what you were originally trying to do anyways):
public bool Remove(T item) {
int index = IndexOf(item);
if (index >= 0) {
RemoveAt(index);
return true;
}
return false;
}
See here for the source.
Alternatively, as others have stated, if you expect the List to contain more than item to be removed, you can use .RemoveAll:
moscowCars.RemoveAll(y => y == cars[x].Name);
And again, to handle the case where nothing is found:
if (moscowCars.RemoveAll(y => y == cars[x].Name) == 0)
{
// Handle no cars to remove
}
You can indeed use IndexOf(item)
this will give you the index of the item, or -1 if 'item' was not found (making this method double as a "contains" as well)
Use simply RemoveAt if you are sure you don't have any duplicated items anyway use the second way.
Solution
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAt(moscowCars.IndexOf(cars[x].Name));
}
}
}
Solution
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAll(o => o == cars[x].Name);
}
}
}
I hope it will help.

Load a list from an array

I have a program that is working except that my data is contained in an array; however, I have found out from you people that I cannot load a dataGridView from an array.
If I had code like this, how would I load a List for the source of the dataGridView1...
// Load some date to indicate what I'm trying to do.
int nColName = 0;
int nColNumberOfOccurances = 1;
int nColTotalTime = 2;
int nColAverageTime = 3;
string[,] strMyArray = new string[2,4];
// load array with test data
for (int i = 0; i < strMyArray.Length; i++)
{
switch (i)
{
case 0:
strMyArray.SetValue("file1.log".ToString(), i, nColName);
strMyArray.SetValue("10".ToString(), i, nColNumberOfOccurances);
strMyArray.SetValue("8989".ToString(), i, nColTotalTime);
strMyArray.SetValue("898.9".ToString(), i, nColAverageTime);
break;
case 1:
strMyArray.SetValue("file2.log".ToString(), i, nColName);
strMyArray.SetValue("5".ToString(), i, nColNumberOfOccurances);
strMyArray.SetValue("4494.5".ToString(), i, nColTotalTime);
strMyArray.SetValue("898.9".ToString(), i, nColAverageTime);
break;
}
}
// convert an array like the above into a List so that I can say...
// myNewListFromArray = strMyArray
// dataGridView1.DataSource = myNewListFromArray;
Arrays works with DataGridView. Your problems is - you using two dimensional array which cannot be used as DataSource.
Instead of array, create a class with properties which represent your data.
Note: important to use a property, because DataGridView binding works with properties only.
public class MyData
{
public string Name { get; set; }
public string NumberOfOccurances { get; set; }
public string TotalTime { get; set; }
public string AverageTime { get; set; }
}
Then use this class in the List
var list = new List<MyData>
{
new MyData
{
Name = "file1.log",
NumberOfOccurances = "10",
TotalTime = "8989",
AverageTime = "898.9"
},
new MyData
{
Name = "file2.log",
NumberOfOccurances = "5",
TotalTime = "4494.5",
AverageTime = "898.9"
},
}
dataGridView1.DataSource = list;

C# Linq "Entity with the same key '0' already added." when inserting multiple rows

I am trying to insert data in bulk, database is MySQL connection is done using Devart LinqConnect.
Here is a code:
DataContext db = new DataContext();
List<XYData> XYDList = new List<XYData>(); // Data Type
List<xydata> xyToBeInsrted = new List<xydata>(); // Database table
XYDList = XYData.genXYData(12, 1234); // Generates 12 example records
foreach (XYData oneXY in XYDList)
{
// Create clear row representation
xydata xy_row = new xydata();
// Assign data from object
xy_row.id = oneXY.Id;
xy_row.Batchid = (int)oneXY.BatchId;
xy_row.Ch = oneXY.Channel;
xy_row.Value = oneXY.Value;
xy_row.Pos = (int)oneXY.Position;
xy_row.Dtm = oneXY.Time;
// Add to list of rows to be inserted
xyToBeInsrted.Add(xy_row);
}
db.xydatas.InsertAllOnSubmit<xydata>(xyToBeInsrted);
db.SubmitChanges();
Last line gives an error "Entity with the same key '0' already added."
When I lower number of items to be generated to 1 then it works. Anything above 1 gives error.
Table has set Auto Increment on record Id field.
Trying to solve that for 2 hours without success.
EDIT:
Data Class:
public class XYData
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Id { get; set; }
public int BatchId { get; set; }
public int Channel { get; set; }
public String Value { get; set; }
public double Position { get; set; }
public DateTime Time { get; set; }
private static Random rand = new Random();
public XYData(int channel = 0, string val = "")
{
Channel = channel;
Value = val;
Position = 0;
Time = DateTime.Now;
}
public static List<XYData> genXYData(int howMany, int batchId)
{
List<XYData> _allXYData = new List<XYData>();
for (int i = 0; i < howMany; i++)
{
XYData _singleXY = new XYData();
_singleXY.BatchId = batchId;
for (int j = 64 * (1 << i); j > 0; j--)
{
uint k = (uint)rand.Next(int.MaxValue);
_singleXY.Value += k.ToString("X8");
}
_allXYData.Add(_singleXY); // Add to list
}
return _allXYData; // Return list of generated data.
}
}
Something like this may be needed on your model definition -
[Column(IsPrimaryKey=true, IsDbGenerated=true)]
public int Id { get; set; }
http://www.devart.com/linqconnect/docs/PrimaryKeyMapping.html

Categories

Resources