List information disappearing - c#

THIS IS HOMEWORK: I have a program that consists of two winforms and three classes. The program does the work it is supposed to do for the main form and displays it appropriately onto the textbox of the main form. In addition to displaying the information, it is also saved to a string list. The data consists of order information.
The string list passes that information along to a method in another class and stores it in a list as it is supposed to do. After this is done, I press a button which opens up another form. In this form I enter an order number. What is supposed to happen is that a method compares the order number entered with the row number of the list and return that information, whereupon it is displayed in the textbox of the second form.
That is what is supposed to happen. Instead, when it is time to compare the order number with the row number of the list, the list data is gone and I cannot figure out why. Here is my code that pertains:
private void btnPaymentButton_Click(object sender, EventArgs e)
{
amountPaid = double.Parse(this.txtAmountPaid.Text);
orderObject.GetChangeDue(orderObject.TotalAmountDue, amountPaid);
this.txtNumberOfPizzaOrdered.Clear();
this.txtNumberOfCokesOrdered.Clear();
this.txtAmountDue.Clear();
this.txtAmountPaid.Clear();
this.lblYourOrder.Visible = true;
this.rtxtYourOrder.Visible = true;
this.rtxtYourOrder.Text = orderObject.OrderSummary(amountPaid);
//storeOrderObject = new DailySummary(orderObject.OrderSummary(amountPaid));
storeOrderObject = new DailySummary(this.rtxtYourOrder.Text);
}
private void btnDailySummary_Click(object sender, EventArgs e)
{
DailySummaryForm form = new DailySummaryForm();
// this.Visible = false;
form.Show();
}
........
public class DailySummary
{
//declare variables
int numberOfCokes = 0,
numberOfPizzas = 0,
totalOfCokes = 0,
totalOfPizzas = 0,
orderNumberRequest = 0;
string orderFromForm1 = "",
getAllTheOrders = "",
getAnOrder = "";
List<string> pizzaOrderList = new List<string>();
public DailySummary(string orderForm)
{
orderFromForm1 = orderForm;
StoreOrder(orderFromForm1);
}
public DailySummary(int orderRequest)
{
orderNumberRequest = orderRequest;
GetOrder(OrderNumberRequest);
}
public int OrderNumberRequest
{
get
{
return this.orderNumberRequest;
}
}
//store order
public void StoreOrder(string orderFromForm1)
{
pizzaOrderList.Add(orderFromForm1);
}
//get the order
public string GetOrder(int OrderNumberRequest)
{
for (int row = 0; row < pizzaOrderList.Count; row++)
{
if (row == (OrderNumberRequest - 1))
{
getAnOrder = pizzaOrderList[row];
}
}
return getAnOrder;
}
........
public partial class DailySummaryForm : Form
{
int orderNumberRequest = 0;
//instantiate a from object
OrderForm formObject;
DailySummary summaryObject;
public DailySummaryForm()
{
InitializeComponent();
}
private void btnOrderNumberButton_Click(object sender, EventArgs e)
{
orderNumberRequest = int.Parse(this.txtOrderNumber.Text);
summaryObject = new DailySummary(orderNumberRequest);
this.rtxtDisplayOutput.Visible = true;
this.rtxtDisplayOutput.Text = summaryObject.GetAnOrder;
}

In your method btnPaymentButton_Click you create an instance of the DailySummary class, then later on when your in the DailySummaryForm you create a new instance of the DailySummary Class.
These instances are separate and therefore do not share the same values.
As your not persisting values to the DB you'll probably want to:
look into making your DailySummary Static (which will make it accessable throughout your
winform application). (It's not typically good practice to have too many global (static) variables hanging around, but without a persistence engine where you can store your Daily Summary you need a common place to look it up.
Pass the initialized instance of the DailySummary class to your DailySummaryForm. (The DailySummaryForm could expose a public property. The drawback of this method is if your switching between both forms and each form modified your summary class, your going to constantly have to pass it back and forth between the forms.

DailySummaryForm is creating a new instance of
DailySummary.
and that is why it is empty.

Related

How can I simplify this code with a for loop to update many controls?

I have done the following code and works well. I am wondering how I can do a for loop to clean this code from 38 lines into 2 lines.
s0s.Text = seg[0].start.ToString("X8");
s0e.Text = seg[0].end.ToString("X8");
s1s.Text = seg[1].start.ToString("X8");
s1e.Text = seg[1].end.ToString("X8");
// .. many more ..
s19s.Text = seg[19].start.ToString("X8");
s19e.Text = seg[19].end.ToString("X8");
I can obviously do the seg[i] substitution, but how do i do it with the text boxes?
I suppose you could use the Controls property and call OfType<T>() to get all the instances of TextBoxes in your Form instance
Filters the elements of an IEnumerable based on a specified type.
Then convert the results to a Dictionary based on the control Name
// this could potentially be done in the constructor
var dict = Controls.OfType<TextBox>().ToDictionary(x => x.Name);
for (int i = 0; i < 19; i++)
{
dict[$"s{i}s"].Text = $"{seg[i].Start:X8}";
dict[$"s{i}e"].Text = $"{seg[i].End:X8}";
}
Note : This code is untested and only a guide to a possible solution
I'd be tempted to do it this way. First create two lists of your controls, the starts and the ends:
var starts = new List<TextBox>
{
s0s,
s1s,
//...
s19s
};
var ends = new List<TextBox>
{
s0e,
s1e,
//...
s19e
};
Then loop over each list:
var i = 0;
foreach (var start in starts)
{
start.Text = seg[i].start.ToString("X8");
++i;
}
i = 0;
foreach (var end in ends)
{
start.Text = seg[i].end.ToString("X8");
++i;
}
Your indexes and control numbers would need to line up perfectly though.
Note: Like TheGeneral's code, this is untested (neither of us wants to create a form with 38 text boxes with specific names)
Based on the textboxes names I would suggest alternative approach to use control designed to display collection of things - DataGridView would be one of the options.
With data binding you can achieve little bit more maintainable code
public class MyItem
{
public int Start { get; set; }
public int End { get; set; }
}
In the form create a datagridview with two bounded columns, you can do this in winforms designer without manually writing the code below.
// constructor
public MyForm()
{
var startColumn = new DataGridViewTextBoxColumn();
startColumn.DataPropertyName = "Start"; // Name of the property in MyItem class
startColumn.DefaultCellStyle.Format = "X8";
var endColumn = new DataGridViewTextBoxColumn();
endColumn.DataPropertyName = "End"; // Name of the property in MyItem class
endColumn.DefaultCellStyle.Format = "X8";
myDataGridView.Columns.AddRange(startColumn, endColumn);
myDataGridView.AutoGenerateColumns = false;
}
private void Form1_Load(object sender, EventArgs e)
{
var items = new List<MyItem>
{
new MyItem { Start = 10, End = 20 },
new MyItem { Start = 11, End = 19 },
new MyItem { Start = 12, End = 18 }
};
myDataGridView.DataSource = items;
}
firstly when you create they variables insert them all to an array. then run a loop as following:
for (int i; int < 19(your list); i++)
{
your list[i].Text = seg[i].start.ToString("X8");
your list[i].Text = seg[i].end.ToString("X8");
}

WinForm Button stops working after 1-2 uses

I have a program that quizzes the user by naming a Country (from a list) and asks the user to input it's Capital. If they get it correct, a counter for correct answers is shown with +1 added to it. If it is wrong, the same thing goes but for the incorrect counter. I finished the code for it, but whenever I use the Check Answer button, it doesn't verify the input from the TextBox anymore, and none of the counters (correct or incorrect) change at all. If the first one is right and the second is wrong, it counts both 1 for correct and 1 for incorrect. After that the code under the Check Answer button doesn't execute anymore. If I got 2 right or 2 wrong it only counts the first 1 and stops working after.
{
// Declare structure
struct Country
{
// Declare strings
public string countryName;
public string capital;
}
public partial class Form1 : Form
{
// Create List for CourseInfo
private List<Country> countryList = new List<Country>();
Country currentCountry;
public Form1()
{
InitializeComponent();
}
private void ReadFile()
{
try
{
// Call StreamReader to use imported file
StreamReader inputFile;
string line;
Country entry = new Country();
// Delimiter to separate values in text file
char[] delim = { ',' };
// Open text file
inputFile = File.OpenText("countries.txt");
while (!inputFile.EndOfStream)
{
line = inputFile.ReadLine();
// Tokenize the strings separated by the delimiter ','
string[] tokens = line.Split(delim);
entry.countryName = tokens[0]; // Tokenized entry for COUNTRY
entry.capital = tokens[1]; // Tokenized entry for CAPITAL
countryList.Add(entry);
}
}
catch (Exception ex)
{
// Shows error message
MessageBox.Show(ex.Message);
}
}
private void DisplayCountry()
{
// Create random variable
Random rand = new Random();
// Country us randomly chosen from the list
int countryPosition = rand.Next(countryList.Count);
// Selected country
currentCountry = countryList[countryPosition];
// Show selected country in Label
countryAnswerLabel.Text = currentCountry.countryName;
}
private void ExitButton_Click(object sender, EventArgs e)
{
// Closes the form
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
// Call method to load StreamReader with the file
ReadFile();
}
private void QuizButton_Click(object sender, EventArgs e)
{
// Call method to show random country
DisplayCountry();
}
private void CheckAnswerButton_Click(object sender, EventArgs e)
{
// Declare integer variables for the counters and set to 0
int correctCounter = 0;
int incorrectCounter = 0;
// If the input is correct, +1 for the correct counter
if (currentCountry.capital == capitalAnswerTextBox.Text)
{
correctCounter++;
correctLabel.Text = correctCounter.ToString();
}
// If the input is incorrect, +1 for the incorrect counter
else
{
incorrectCounter++;
incorrectLabel.Text = incorrectCounter.ToString();
}
}
private void NextQuestionButton_Click(object sender, EventArgs e)
{
// Clears input TextBox
capitalAnswerTextBox.Text = string.Empty;
DisplayCountry();
}
}
Notice that whenever CheckAnswerButton_Click is executed, the variables correctCounter and incorrectCounter are initialised to 0. So every time you press the button, you start counting the answers from 0 again. So you will always be setting one of label's Text to "1". In case that label already shows "1", it would seem like it's "not doing anything".
Therefore, you should move the declarations of correctCount and incorrectCounter to outside the CheckAnswerButton_Click method:
// Declare integer variables for the counters and set to 0
int correctCounter = 0;
int incorrectCounter = 0;
private void CheckAnswerButton_Click(object sender, EventArgs e)
{
// If the input is correct, +1 for the correct counter
if (currentCountry.capital == capitalAnswerTextBox.Text)
{
correctCounter++;
correctLabel.Text = correctCounter.ToString();
}
// If the input is incorrect, +1 for the incorrect counter
else
{
incorrectCounter++;
incorrectLabel.Text = incorrectCounter.ToString();
}
}
This way, they will retain their value after CheckAnswerButton_Click has returned.

"Collection was modified; enumeration operation may not execute" when running the same background worker on 2+ instances of a form simultaneously

I have a c# windows form where the user enters a set of parameters, and those parameters are then analyzed against a set of data to return a result. This analysis takes place on a background worker, by initializing a Backtest object and iterating over a string list symbolParams built from the values passed in through the form. When running the worker on one form, it works properly.
However, if I open up a second form, put in a new set of parameters, and run the worker on that form while the worker on the first form is still running, I get a "Collection was modified" error on the string list.
Seems as though the two background workers are affecting each other's symbolParams list somehow. What's happening? How can this be fixed to allow multiple instances of this form to run this background worker simultaneously?
OptimizerForm.cs
public partial class OptimizerForm : Form
{
public static List<List<String>> backtestSymbolParams = new List<List<String>> { };
private void button15_Click(object sender, EventArgs e)
{
//Get parameters from the form
//Make a list for every param
string[] startEndTimes = textBox3.Text.Split(',');
string[] incrementPrices = textBox4.Text.Split(',');
string[] incrementSizes = textBox5.Text.Split(',');
string[] autoBalances = textBox6.Text.Split(',');
string[] hardStops = textBox7.Text.Split(',');
//Add every combo to symbol test params
for (int a = 0; a < startEndTimes.Length; a++)
{
for (int b = 0; b < incrementPrices.Length; b++)
{
for (int c = 0; c < incrementSizes.Length; c++)
{
for (int d = 0; d < autoBalances.Length; d++)
{
for (int f = 0; f < hardStops.Length; f++)
{
backtestSymbolParams.Add( new List<string> { symbol, startEndTimes[a].Split('-')[0], startEndTimes[a].Split('-')[1], incrementPrices[b],
incrementSizes[c], autoBalances[d], hardStops[f] });
}
}
}
}
}
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Initialize Backtest instance with parameters gathered from the form
Backtest backtest = new Backtest(backtestSymbolParams, backtestSymbolDates, sender as BackgroundWorker);
TestResult testResult = new TestResult();
//Run the analysis
testResult = backtest.Run();
e.Result = testResult;
}
}
Backtest.cs
//Backtest Constructor
public Backtest(List<List<string>> _symbolParams, Dictionary<string, List<string>> _symbolDates, BackgroundWorker _bw)
{
symbolParams = _symbolParams;
symbolDates = _symbolDates;
bw = _bw;
}
//Backtest.Run()
public TestResult Run()
{
int symbolCount = 1;
//Collection modified exception occurs here
foreach (List<string> symbolParam in symbolParams) {
//do stuff
}
}
It seems like your symbolParams variable in Backtest class is static, so simply mark it as private field for your class.
Also you have some issues with naming standards - method parameters should not start with _, though fields should, so your constructor should looks like:
private List<List<String>> _symbolParams = new List<List<String>> { };
//Backtest Constructor
public Backtest(List<List<string>> symbolParams,
Dictionary<string, List<string>> symbolDates,
BackgroundWorker bw)
{
_symbolParams = symbolParams;
_symbolDates = symbolDates;
_bw = bw;
}
And, as far as I can see, you're using BackgroundWorker as Task so probably you should use TPL itself, without old legacy classes

Data reset after leaving a constructor

I have probably a very beginner question,yet I can't figure out why is it like that. I am trying to pass in constructor a StringBuilder which via Debugger I nailed but as soon as my last step in Debugger leaves this constructor which is in different class, it gets back to null. I know that it is a reference type and therefore only a reference gets copied but even if I pass it by reference by "ref" result is the same...maybe I get it wrong or there is something else wrong...
class DifferentClass
{
public void Method()
{
StringBuilder[] PathtoFiles = new StringBuilder[numberOfImages];
for (int i = 0; i < numberOfImages; i++)
{
PathtoFiles[i] = new StringBuilder();
// string pattern for correct file naming/saving
string nameOfFile = string.Format("{0}{1}{2}", adresaPath, i, ".jpg");
PathtoFiles[i].Append(nameOfFile);
}
Pictures picture = new Pictures(ref PathtoFiles);
}
}
class Pictures
{
public StringBuilder[] sb;
public Pictures(ref StringBuilder[] sb)
{
this.sb = sb;
}
public Pictures()
{
}
public void LoadPictures(ImageList img)
{
for (int i = 0; i < sb.Count(); i++)
{
img.Images.Add(string.Format("pic{0}", i), Image.FromFile(sb[i].ToString()));
}
}
}
Upon request I am enclosing another bit of code this time in class where the method LoadPictures gets called:
class ThirdClass
{
DifferentClass diff = new DifferentClass();
Pictures picture = new Pictures();
private void btn_Download_Click(object sender, EventArgs e)
{
diff.Method();
//this is a control data is supposed to be saved in
picture.LoadPictures(imageList1);
}
}
Well there ya go:
class ThirdClass
{
DifferentClass diff = new DifferentClass();
Pictures picture = new Pictures();
private void btn_Download_Click(object sender, EventArgs e)
{
diff.Method();
//this is a control data is supposed to be saved in
picture.LoadPictures(imageList1);
}
}
You are using the default constructor. Which doesn't set StringBuilder[] Pictures.sb
This is assuming of course that code you re-edited is the code you are working with.
In that case you need to figure out how to instantiate DifferentClass, maybe in ThirdClass ctor. And perhaps you want DifferentClass.Method() to return a Picture object you can initialize also in ThirdClass constructor.
There are several ways you can do this. Up to you to choose the best method.
public void Method()
{
// the StringBuilder
// ...
Pictures picture = new Pictures(ref PathtoFiles);
}
initialization of picture is correct. but it is a local variable, and when Method() is completed, you can't access it anymore
you can modify your method to keep result in variable on client-side:
public Pictures Method()
{
// the StringBuilder
// ...
return new Pictures(ref PathtoFiles);
}
client-side
var pics = new DifferentClass().Method();
ImageList imgs = new ImageList();
pics.LoadPictures(imgs);

Dynamic Checkbox from a txt file entry on a WinForm UI

Good Morning;
Actually have 2 questions. My first is what is this called? A Program? A Module?
WhatIsThisCalled()
{
//workToBeDone
}
I'm trying to create dynamic checkbox(s) from each entry in a text file. I'm trying to reuse the code so I have tried to create the module in a logic file. I feel like I've done this correctly, but I can't test it. I can not figure out how to reference
this.Controls.Add(chk[I]);
to the winForm I want to call it on. The error I get is about it being illegal in a static method. I'm only trying to clear the error (last one) so I can see if it will actually put the checkboxes onto the correct winForm Permissions.cs. Here is my Logic.cs module.
public static void getPermText()
{
Stream fileStream = File.Open(dataFolder + PermFile, FileMode.Open);
StreamReader reader = new StreamReader(fileStream);
string line = null;
do
{
line = reader.ReadLine();
if (line == null)
{
break;
}
string[] parts = line.Split('\n');
try
{
int userCount;
userCount = parts.Length;
CheckBox[] chk = new CheckBox[userCount];
int height = 1;
int padding = 10;
for (int i = 0; i <= userCount; i++)
{
chk[i] = new CheckBox();
chk[i].Name = parts.ToString();
chk[i].Text = parts.ToString();
chk[i].TabIndex = i;
chk[i].AutoCheck = true;
chk[i].Bounds = new Rectangle(15, 30 + padding + height, 150, 22);
this.Controls.Add(chk[i]);
height += 22;
}
}
catch
{
}
} while (true);
}
There is one global int userCount = 0; above that module. On Permissions.cs I have this code (with no errors).
public Permissions()
{
InitializeComponent();
}
private void Permissions_Load(object sender, EventArgs e)
{
WidgetLogic.getPermText();
}
Can anyone please direct me as to how, or if it is possible, to replace Permissions with this in a dynamic format?? I think??
Thank you very much in advance for all that look or help. I really appreciate it. Have a Great Day!! :)
I tired very hard to understand what you wanted to say. I think you just want to reference the form where the CheckBoxes should create.
So you should better pass the reference the of the form on which you want to create the controls:
public static void getPermText(System.Windows.Forms.Form targetForm)
{
//code
targetForm.Controls.Add(chk[i]); //changed "this" to "targetForm"
To call the method:
WidgetLogic.getPermText(this); //here "this" refers to the current form
Now where ever you will call this method it will create the controls on your form (the one you're passing as the parameter).
Notify me if I got your question wrong.

Categories

Resources