this is how my GUI looks like
I was working on a project for uni
what it does is reading a text-file
put it in listbox1
then the second button should take the students who succeed to listbox2
but whenever I press the button I get an error
I tried rly hard to search everywhere, but couldn't find the problem
it's just not writing it in listbox2 for no reason
anyone know what should I do?
what do I do to make it work???
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace second_Project
{
public partial class FSS : Form
{
private void FSS_Load(object sender, EventArgs e)
{
}
public FSS()
{
InitializeComponent();
}
public class StdScore
{
public int id;
public string name;
public double xam, Score, Pract;
public string content;
public string[] xx;
}
OpenFileDialog ofd = new OpenFileDialog();
private void button1_Click(object sender, EventArgs e)
{
StdScore StdScore = new StdScore();
ofd.Filter = "TXT|*.txt";
if (ofd.ShowDialog() == DialogResult.OK)
{
StreamReader sr = new StreamReader(ofd.FileName);
while (!sr.EndOfStream)
{
StdScore.content = sr.ReadLine();
string[] info = StdScore.content.Split(' ');
StdScore.xx = new string[info.Length];
listBox1.Items.Add(StdScore.content);
}
sr.Close();
}
}
private void button2_Click(object sender, EventArgs e)
{
StdScore StdScore = new StdScore();
StdScore.xam = 0;
StdScore.Pract = 0;
StdScore.Score = 0;
StdScore.xam += int.Parse(StdScore.xx[2]);
StdScore.Pract += int.Parse(StdScore.xx[3]);
StdScore.Score = StdScore.xam * 0.7 + StdScore.Pract * 0.3;
if (StdScore.xam >= 40 && StdScore.Pract >= 40 && StdScore.Score >= 60)
{
StdScore.xam = (StdScore.xam * 70) / 100;
StdScore.Pract = (StdScore.Pract * 30) / 100;
StdScore.Score = StdScore.xam + StdScore.Pract;
listBox2.Items.Add(StdScore.xx[0] + " " + StdScore.xx[1] + " " + StdScore.xx[2] + " " + StdScore.xx[3] + " " + StdScore.Score + " " + "Succes");
}
}
}
}
When reading the file, you have listBox1.Items.Add(StdScore.content);. This simply adds a string to the ListBox. You should create instances of StdScore INSIDE the while loop and add those instances directly to the ListBox. It's a very bad practice to name your variable the exact same as the class itself. I would expect to see something more like StdScore curScore = new StdScore();. Now you can use curScore and it's clear this is an instance of the class and not the class itself, and you're not trying to access a static member. For class StdScore, you can override the ToString() method to control what is displayed in the ListBox.
So here is StdScore with the ToString() override:
public class StdScore
{
public int id;
public string name;
public double xam, Score, Pract;
public string content;
public string[] xx;
public override string ToString()
{
return content;
}
}
Next, reading the file:
while (!sr.EndOfStream)
{
StdScore curScore = new StdScore();
curScore.content = sr.ReadLine();
curScore.xx = curScore.content.Split(' ');
listBox1.Items.Add(curScore);
}
On to button2 where you want to move students who succeed over to listBox2. Here you need to ITERATE over all the stored StdScore instances that are within listBox1:
private void button2_Click(object sender, EventArgs e)
{
foreach(StdScore curScore in listBox1.Items)
{
curScore.xam = int.Parse(curScore.xx[2]);
curScore.Pract = int.Parse(curScore.xx[3]);
curScore.Score = curScore.xam * 0.7 + curScore.Pract * 0.3;
if (curScore.xam >= 40 && curScore.Pract >= 40 && curScore.Score >= 60)
{
curScore.xam = (curScore.xam * 70) / 100;
curScore.Pract = (curScore.Pract * 30) / 100;
curScore.Score = curScore.xam + curScore.Pract;
string success = curScore.xx[0] + " " + curScore.xx[1] + " " +
curScore.xx[2] + " " + curScore.xx[3] + " " + curScore.Score + " Success";
listBox2.Items.Add(success);
}
}
}
Note that from an Object Oriented Programming perspective, none of this code is correct. The code can be much improved. I simply took your existing code and changed it to "make it work"...at least I think it will; if not, it should give you some good ideas on where to make changes.
Related
in this program, when the Recall button (recallBtn_Click()) is clicked, it calls a method (that calculates directions) from another class which should then call the showPath() method. the show path method should then display its output in a textBox. But the values don't show even though i can see from debugging that the values are being sent to the text box. can anybody tell me where i went wrong?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
storeRetSelect.SelectedIndex = 0;
PrioritySelect.SelectedIndex = 0;
}
public void showPath(List<PathFinderNode> mPath)
{
var T = new Form1().directionsTextBox;
foreach (PathFinderNode node in mPath)
{
if ((node.X - node.PX) > 0) { T.Text += "Right" + System.Environment.NewLine ; }
if ((node.X - node.PX) < 0) { T.Text += "Left" + System.Environment.NewLine; }
if ((node.Y - node.PY) > 0) { T.Text += "UP" + System.Environment.NewLine; }
if ((node.Y - node.PY) < 0) { T.Text += "Down" + System.Environment.NewLine; }
}
}
private void recallBtn_Click(object sender, EventArgs e)
{
var path = new pathPlan();
string desigString = inputTextBox.Text;
int[] desig = new int[3];
for (int i = 0; i < desigString.Length; i++) { desig[i] = (int)char.GetNumericValue(desigString[i]); }
path.Recall(desig[1], desig[2], (-1) * desig[0]);
}
}
With this line you are initialising a new object and get the reference of the textbox there.
var T = new Form1().directionsTextBox;
But I assume you want to use the textbox of the form which is allready open. Change the line to the following to access the textbox of the current object.
var T = this.directionsTextBox;
I am working on a project in c# visual studio in which i am attempting to make a bowling calculator. i have made a class for frames which contains a throw1 and throw2. I first fill the array of classes with one button and calculate score after game completion. when i go to calculate score it tells me i have null values.below is my form code the class is just
class frames
{
public int intThrow1;
public int intThrow2;
}
the main form is
public partial class Form1 : Form
{
frames[] frame = new frames[11];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
int intFrst = int.Parse(textBox1.Text);
int intScnd = int.Parse(textBox2.Text);
if (lbxScorecard.Items.Count <= 21)
{
int intIndx = 0;
if (intFrst == 10)
{
frame[intIndx] = new frames();
frame[intIndx].intThrow1 = intFrst;
frame[intIndx].intThrow2 = 0;
lbxScorecard.Items.Add(frame[intIndx].intThrow1);
lbxScorecard.Items.Add(frame[intIndx].intThrow2);
intIndx += 2;
}
else
{
frame[intIndx] = new frames();
frame[intIndx].intThrow1 = intFrst;
frame[intIndx].intThrow2 = intScnd;
lbxScorecard.Items.Add(frame[intIndx].intThrow1);
lbxScorecard.Items.Add(frame[intIndx].intThrow2);
intIndx++;
}
}
else
{
MessageBox.Show("max throws");
}
}
private void button2_Click(object sender, EventArgs e)
{
int intScore = 0;
for (int index = 0; index <= 11; index++)
{
if (frame[index].intThrow1 == 10 && index < 9) // here is where it throws a null exception stating the index may be empty
{
if (frame[index + 1].intThrow1 != 10)
{
intScore = intScore + frame[index].intThrow1 + frame[index + 1].intThrow1 + frame[index + 1].intThrow2;
}
else if (frame[index].intThrow1 == 10)
{
intScore = intScore + frame[index].intThrow1 + frame[index + 1].intThrow1 + frame[index + 2].intThrow1;
}
}
else if (frame[index].intThrow1 + frame[index].intThrow2 == 10 && index < 9) //it was throwing the same exception here until i added && index<9 in the if statements.
{
intScore = intScore + frame[index].intThrow1 + frame[index].intThrow2 + frame[index + 1].intThrow1;
}
else
{
intScore = intScore + frame[index].intThrow1 + frame[index].intThrow2;
}
}
MessageBox.Show(intScore.ToString());
}
}
Problem is:
frames[] frame = new frames[11];
You also need to instantiate each element of the array like you did in the button1_Click function:
frame[intIndx] = new frames();
Also note that you have a class variable frame and the same one in button2_Click which is probably a bad idea.
This question already has answers here:
Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
(22 answers)
Closed 6 years ago.
I have been learning before about threading but in C++. Now for the first time I'm trying to configure this code to work corectly but without CheckIllegal ... = false.
I have been trying to put delegates in there and lots of other stuff but the I getting the same problem. Both threads are entering the methof WriteInLog and I can't really see how to make this work.
Anyone has an idea and explanation?
namespace viseNitniRad
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int firstNum = 0;
private int secondNum = 0;
public Thread firstThread;
public Thread secondThread;
public void WriteInLog(string message)
{
lock (textBox3)
{
textBox3.Text += message + Environment.NewLine;
}
}
private void CheckInput()
{
int pom = 0;
firstNum = int.Parse(textBox1.Text);
secondNum = int.Parse(textBox2.Text);
if (firstNum > secondNum) {
pom = secondNum;
secondNum = firstNum;
firstNum = pom; }
WriteInLog("Prvi broj: " + firstNum.ToString());
WriteInLog("Drugi broj: " + secondNum.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
CheckInput();
}
public delegate void ThreadSum();
public delegate void ThreadUmn();
public void Threadsumm()
{
int suma = 0;
for (int i = firstNum; i < secondNum; i++)
suma += i;
WriteInLog("Suma= " + suma.ToString() + " kraj: " + DateTime.Now.ToString());
}
public void ThreadUmno()
{
int umnozak = 1;
for (int i = firstNum; i < secondNum; i++)
umnozak*= i;
WriteInLog("Umnozak= " + umnozak.ToString() + " kraj: " + DateTime.Now.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
WriteInLog("Pocetak svih izracuna u: " + DateTime.Now.ToString());
firstThread = new Thread(new ThreadStart(Threadsumm));
secondThread = new Thread(new ThreadStart(ThreadUmno));
firstThread.Start();
secondThread.Start();
}
}
}
To access control from non-UI thread you have to use Control.Invoke method https://msdn.microsoft.com/en-us/library/a1hetckb(v=vs.110).aspx
Instead of Threads you can use BackgroundWorker
https://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
Also:
WinForm Multithreading. Use backgroundWorker or not?
If anyone comes here and want to know exactly the answer on this question, here it is.
I didn't want to change anything so I learn something about invoke. Furthermore, here's the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace viseNitniRad
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int firstNum = 0;
private int secondNum = 0;
public Thread firstThread;
public Thread secondThread;
public void WriteInLog(string message)
{
if (this.textBox3.InvokeRequired)
{
ThreadSum ts = new ThreadSum(WriteInLog);
this.Invoke(ts, new object[] { message });
}
else
{
this.textBox3.Text += message + Environment.NewLine;
}
}
private void CheckInput()
{
int pom = 0;
firstNum = int.Parse(textBox1.Text);
secondNum = int.Parse(textBox2.Text);
if (firstNum > secondNum) {
pom = secondNum;
secondNum = firstNum;
firstNum = pom; }
WriteInLog("Prvi broj: " + firstNum.ToString());
WriteInLog("Drugi broj: " + secondNum.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
CheckInput();
}
public delegate void ThreadSum(string message);
public delegate void ThreadUmn();
public void Threadsumm()
{
int suma = 0;
for (int i = firstNum; i < secondNum; i++)
suma += i;
WriteInLog("Suma= " + suma.ToString() + " kraj: " + DateTime.Now.ToString());
}
public void ThreadUmno()
{
int umnozak = 1;
for (int i = firstNum; i < secondNum; i++)
umnozak*= i;
WriteInLog("Umnozak= " + umnozak.ToString() + " kraj: " + DateTime.Now.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
WriteInLog("Pocetak svih izracuna u: " + DateTime.Now.ToString());
firstThread = new Thread(new ThreadStart(Threadsumm));
secondThread = new Thread(new ThreadStart(ThreadUmno));
firstThread.Start();
secondThread.Start();
}
}
}
As you can see I made little change in function WriteInLog, where I deleted lock method and put an condition if invokeRequired to initialize Delegate to run the same method and than Invoke him, if not, just to update the same textbox3.
Thank you all! :)
Error: the class choosedisplay can be designed, but is not the first class in the file. Visual Studio requires that designers use the first class in the file.
How to move the class code so that it is in the first class.
I dont Know about program i am a Mechanical Engineer. I trying to do my project in C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using GraphSynth.Representation;
using GraphSynth.Forms;
using GraphSynth.Generation;
namespace GraphSynth.Forms
{
public class chooseViaHumanGui : RecognizeChooseApply
{
public override int choose(List<option> options, candidate cand)
{
SearchIO.output("There are " + options.Count.ToString() + " recognized locations.", 2);
if (options.Count == 0)
{
SearchIO.output("Sorry there are no rules recognized.", 0);
return int.MinValue;
}
else if (options.Count > Program.settings.maxRulesToDisplay)
{
SearchIO.output("Sorry there are too many rules to show.", 0);
return int.MinValue;
}
else
{
SearchIO.output("Double-click on one to show the location.", 2);
chooseDisplay choiceDisplay = new chooseDisplay();
choiceDisplay.promptUser(options, (Boolean)(cand.recipe.Count == 0));
return choiceDisplay.choice;
}
}
public override double[] choose(option RC, candidate cand)
{ return null; }
#region Constructors
public chooseViaHumanGui(Boolean _display)
: base(Program.seed, Program.rulesets, Program.settings.maxRulesToApply, _display,
Program.settings.recompileRules, Program.settings.execDir, Program.settings.compiledparamRules) { }
#endregion
}
// This is the class Program for choose display //
public partial class chooseDisplay : Form
{
#region Fields
List<option> rulesToDisplay = new List<option>();
List<int> optionNumbers = new List<int>();
public int choice = int.MinValue;
System.Windows.Forms.Timer checkForStopTimer = new System.Windows.Forms.Timer();
#endregion
public chooseDisplay()
{
checkForStopTimer.Tick += new EventHandler(processTimer_Tick);
checkForStopTimer.Interval = 500;
checkForStopTimer.Start();
}
public void promptUser(List<option> RCs, Boolean hideUndo)
{
InitializeComponent();
rulesToDisplay = RCs;
string ruleNo, location;
int option = 0;
this.Text = "Choices from RuleSet #" + RCs[0].ruleSetIndex.ToString();
for (int i = 0; i != rulesToDisplay.Count; i++)
{
option = i + 1;
ruleNo = rulesToDisplay[i].ruleNumber.ToString();
location = rulesToDisplay[i].location.ToString();
recognizedRulesList.Items.Add(option.ToString() + ".\t" + ruleNo + "\t" + location);
optionNumbers.Add(i);
}
if (hideUndo) this.undoButton.Enabled = false;
ShowDialog();
}
private void showGraph_Click(object sender, EventArgs e)
{
SearchIO.addAndShowGraphDisplay(rulesToDisplay[recognizedRulesList.SelectedIndex].location.copy(),
"Recognized Location " + recognizedRulesList.SelectedItem.ToString());
}
private void removeFromList_Click(object sender, EventArgs e)
{
int numToRemove = recognizedRulesList.CheckedIndices.Count;
if (numToRemove == recognizedRulesList.Items.Count)
{
MessageBox.Show("You cannot remove all possible options.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (numToRemove == recognizedRulesList.Items.Count - 1)
{
int[] toRemove = new int[numToRemove];
recognizedRulesList.CheckedIndices.CopyTo(toRemove, 0);
for (int i = numToRemove; i != 0; i--)
{
if (toRemove[i - 1] != optionNumbers.Count)
{
recognizedRulesList.Items.RemoveAt(toRemove[i - 1]);
optionNumbers.RemoveAt(toRemove[i - 1]);
}
}
if (DialogResult.Yes == MessageBox.Show(
"You are removing all but one option [" +
recognizedRulesList.Items[0].ToString() +
"]. Would you like to apply this option?",
"Apply Remaining Option?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
choice = optionNumbers[0];
this.Close();
}
}
else
{
int[] toRemove = new int[numToRemove];
recognizedRulesList.CheckedIndices.CopyTo(toRemove, 0);
for (int i = numToRemove; i != 0; i--)
{
if (toRemove[i - 1] != optionNumbers.Count)
{
recognizedRulesList.Items.RemoveAt(toRemove[i - 1]);
optionNumbers.RemoveAt(toRemove[i - 1]);
}
}
}
}
private void applyButton_Click(object sender, EventArgs e)
{
int numChecked = recognizedRulesList.CheckedIndices.Count;
checkForStopTimer.Stop();
if (numChecked == 0)
{
MessageBox.Show("No Options Checked.", "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
checkForStopTimer.Start();
}
else if (numChecked == 1)
{
if (!Program.settings.confirmEachUserChoice ||
(DialogResult.Yes == MessageBox.Show(
"Apply Option: " + recognizedRulesList.CheckedItems[0].ToString() + "?",
"Apply Option?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)))
{
int[] toSaveVector = new int[numChecked];
recognizedRulesList.CheckedIndices.CopyTo(toSaveVector, 0);
choice = optionNumbers[toSaveVector[0]];
this.Close();
}
else checkForStopTimer.Start();
}
else if (DialogResult.Yes == MessageBox.Show(
"You cannot apply all of these at the same time. Would you simply like to remove all unchecked Options?", "Remove Unchecked?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
int[] toSaveVector = new int[numChecked];
recognizedRulesList.CheckedIndices.CopyTo(toSaveVector, 0);
List<int> toSave = new List<int>(toSaveVector);
for (int i = recognizedRulesList.Items.Count; i != 0; i--)
{
if (!toSave.Contains(i - 1))
{
recognizedRulesList.Items.RemoveAt(i - 1);
optionNumbers.RemoveAt(i - 1);
}
}
checkForStopTimer.Start();
}
else checkForStopTimer.Start();
}
void processTimer_Tick(object sender, EventArgs e)
{
if (Program.terminateRequest)
{
recognizedRulesList.SetItemChecked(recognizedRulesList.Items.Count - 1, true);
for (int i = 0; i != recognizedRulesList.Items.Count - 1; i++)
recognizedRulesList.SetItemChecked(i, false);
applyButton_Click(sender, e);
}
}
private void undo_Click(object sender, EventArgs e)
{
if ((!Program.settings.confirmEachUserChoice ||
(DialogResult.Yes == MessageBox.Show("Undo the last rule that was applied?",
"Undo Last Rule?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))))
{
choice = -1;
this.Close();
}
}
private void stopButton_Click(object sender, EventArgs e)
{
if ((!Program.settings.confirmEachUserChoice ||
(DialogResult.Yes == MessageBox.Show("Send Stop message to Generation Process?",
"Send Stop?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))))
{
choice = int.MinValue;
this.Close();
}
}
}
}
Look here: https://stackoverflow.com/a/8864376/3317555. Basically the choosedisplay class is sharing a file with another class. All you should have to do is move choosedisplay into it's own file.
EDIT: Fixed bad wording.
You've got two classes declared in the same code file. Move the second one to a different file.
EDIT: Actually, as the second is a form and is probably what that code file was created for in the first place, you should probably move the first class out into its own file.
it's not recognizing my lstSectionNumber (Tickets.TicketForm.lastSectionNumber is inaccessible due to its protection level). Hopefully I explained everything clearly, I'm just recently started learning C#, any help would be appreciated. Thank you in advance.
public class TicketOrder
{
private static int premiumTicket = 40;
private static int basicTicket = 20;
private static int serviceCharge = 2;
private TicketForm form = new TicketForm();
public double CalcTicketCost(int section, double quantity)
{
double amount = 0;
if (int.Parse(form.lstSectionNumber.SelectedItem.Value) <= 150)
{
amount = (quantity*premiumTicket) + (quantity*serviceCharge);
return amount;
}
else
{
amount = (quantity*basicTicket) + (quantity*serviceCharge);
}
return amount;
}
}
Code-behind:
public partial class TicketForm : System.Web.UI.Page
{
int myInt;
public const double premiumTicket = 40;
public const double basicTicket = 20;
public const double serviceCharge = 2;
TicketUser user = new TicketUser();
TicketOrder order = new TicketOrder();
protected void Page_Load(object sender, EventArgs e)
{
// This disables the unobtrusive validation in order to see the result
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
// This will keep my five numbers in my list box without adding more with a refresh of a page
if (!IsPostBack)
{
Random RandomSection = new Random();
for (int i = 0; i < 5; i++)
{
// Created a list box with five random numbers from 1 to 300
myInt = RandomSection.Next(1, 300);
lstSectionNumber.Items.Add(myInt.ToString());
}
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
// I also added TextMode="Number"to my <asp:TextBox ID="txtNumberOfTickets"
// runat="server" Height="18px" Width="134px"></asp:TextBox> code in order
// to get rid of an error incase I left my txtNumberOfTicket empty
int section = Convert.ToInt32(lstSectionNumber.SelectedValue);
double ticketQuantity = Convert.ToInt32(txtNumberOfTickets.Text);
//This label displays users first and last names, number of tickers, seat section number and ticket price
lblPrice.Text = txtFirstName.Text + " " +
txtLastName.Text + ", " +
txtNumberOfTickets.Text + " " +
"Tickets in Section:" + " " +
lstSectionNumber.SelectedValue + "," +
" Total Cost is: " +
order.CalcTicketCost(section, ticketQuantity).ToString("C");
}
protected void btnCreateAccount_Click(object sender, EventArgs e)
{
user.firstName = txtFirstName.Text;
user.lastName = txtLastName.Text;
user.username = txtUserName.Text;
lblCreateAccount.Text = user.CreateAccount();
}
}
Simply give your constructor an empty body
change
public TicketOrder()
to
public TicketOrder() { }
TO solve your other problem, you are trying to make a NEW page, but asp.NET has already made a page for this page load and populated the values for you. You should Pass the current page object into your TicketOrder constructor and save instead.
Like so:
public TicketOrder(TicketForm form)
{
this.form = form;
}
and change in TicketOrder
private TicketForm form = new TicketForm();
to
private TicketForm form;
and change in TicketForm
TicketOrder order = new TicketOrder();
to
TicketOrder order;
public TicketForm()
{
this.order = new TicketOrder(this);
}
Well, I figured it out.
if (section <= 150)
{ amount = (quantity * premiumTicket) + (quantity * serviceCharge);
return amount;