Calculation is wrong - c#

What should happen
My exexcrise is it to prgramm a calculator which is able to do calculations in 'queue'.
Example:
User enters first number in txtZahl and then clicks one of the button. The needed calculation should be saved in the list numbers and txtZahl should be cleared. The user can now enter a new number and press a button etc.
When the user clicks on btnEqu the foreach should take every calculation from the list and do the calculation. If this is done the result should be displayed in txtZahl.
Problem
The calculations are not correct. For example I get 0.00 as result for 4-3.
I know that the idea with the extra class is not the best way, but I would like to keep it, to see what my teacher thinks about it.
Thank you for helping!
Code:
Form1.cs
double ergebniss = 0;
Boolean firstRun = true;
List<Rechnung> numbers = new List<Rechnung>();
Rechnung.RechenArt lastArt;
private void btnMinus_Click(object sender, EventArgs e)
{
if (isValid())
{
if (firstRun)
{
ergebniss = Convert.ToDouble(txtZahl.Text);
}
numbers.Add(new Rechnung(Convert.ToDouble(txtZahl.Text), Rechnung.RechenArt.Subtraktion));
lastArt = Rechnung.RechenArt.Subtraktion;
clearAndFocus();
}
}
private void btnEqu_Click(object sender, EventArgs e)
{
foreach (Rechnung r in numbers)
{
switch (r.getArt())
{
case Rechnung.RechenArt.Subtraktion:
{
ergebniss -= r.getNumber();
break;
}
}
}
txtZahl.Text = ergebniss.ToString("f2");
}
}

if (firstRun)
{
ergebniss = Convert.ToDouble(txtZahl.Text);
firstRun = false;
return;
}
first you forgot to
firstRun = false; after that
then I advice you to display just clean string
txtZahl.Text = ergebniss.ToString();
you also doesn't use lastArt variable don't know if that's necessary.

Related

Re-Enabling Button Based on Condition (C#)

What I am trying to do is simple (I cannot figure it out of course). I am making a sample shop with an inventory system in Winform App format where if on the customer side the "Place Order" button is clicked it deducts from inventory; the amount deducted depends on the quantity of the item ordered. Anyway with this code,
private void button7_Click(object sender, EventArgs e)
button7.Enabled = true;
//Read in value
int qty = Convert.ToInt32(nudQuantity.Value);
if ((rdoSmallCup.Checked & rdoStraw.Checked) == true) {
//Removing four from inventory for strawberry after an order is made
InvStrawberry = InvStrawberry - (4 * qty);
if (InvStrawberry <= 0) {
button7.Enabled = false;
} else {
button7.Enabled = true;
}
label17.Text = Convert.ToString(InvStrawberry);
I am seeing that while it does compile with no errors once the inventory for strawberry has fallen past zero (it will actually be a negative value which I do not want but is another question for another time) the Place Order button ("Button 7") will be grayed out and unusable which is the goal but once inventory is added again this button is still unusable. Can someone explain how I can have this button re-enabled (even though I said it in the 'else' condition)?
Ron and Heretic's comments are right. You cannot access the code in Button7 click event handler once it has been 'disabled'. The only way to enable it again is from outside logic, say after you added additional items into the inventory, you can enable the button right after that.
Also you can can be simplify a bit:
private void button7_Click(object sender, EventArgs e)
//Read in value
int qty = Convert.ToInt32(nudQuantity.Value);
if ((rdoSmallCup.Checked & rdoStraw.Checked) == true) {
//Removing four from inventory for strawberry after an order is made
InvStrawberry = InvStrawberry - (4 * qty);
if (InvStrawberry <= 0)
button7.Enabled = false;
label17.Text = Convert.ToString(InvStrawberry);
...
This code will allow an infinite number of subtraction. Hence, you will need a control that will stop the subtraction when you go below zero.
private void button7_Click(object sender, EventArgs e){
// I have no idea why you have enabled the button here, mate
//Converting the quantity
int qty = Convert.ToInt32(nudQuantity.Value);
if((roSmallCup.Checked & rdoStraw.Checked) == true) {
//triggers when the Inventory of strawberry is more than zero
if( (InvStrawberry - (4 * qty)) > 0 ){
InvStrawberry = InvStrawberry - (4 * qty);
} else
{
button7.ENabled = false;
MessageBox.Show("We are out of inventory,Sorry!");
}
label17.Text = Convert.ToString(InvStrawberry);
}
}
If you want the button to possibly update every time that you change the value of InvStrawberry then the best option is to make a property for InvStrawberry and update the status of the button there. That cuts down the logic that you need to use right throughout your code.
Try this:
public class StrawberryForm : Form
{
private int _invStrawberry = 0;
private int InvStrawberry
{
get
{
return _invStrawberry;
}
set
{
_invStrawberry = value;
button7.Enabled = _invStrawberry > 0;
}
}
private void button7_Click(object sender, EventArgs e)
{
int qty = Convert.ToInt32(nudQuantity.Value);
if ((rdoSmallCup.Checked & rdoStraw.Checked) == true)
{
this.InvStrawberry -= 4 * qty;
label17.Text = Convert.ToString(this.InvStrawberry);
}
}
}
you need to move this:
if (InvStrawberry <= 0) {
button7.Enabled = false;
} else {
button7.Enabled = true;
}
to an Updae method or loop that will check it regularly, right now its in your click, and therefore will never get called to enable it again once it is disabled, since at that point you cant click on it.
also, say you have two variables, numberStrawberries representing youre remaining inventory, and lot representing the four strawberries you put in a purchase...
if(numberStrawberries >= lot){
//we have strawberries, and more at least 4 or more
numberStrawberries-=lot;
}else if(numberStrawberries!=0 && numberStrawberries < lot){
//we have strawberries but only (remaining)
//how many were short(how many we have is still in numberStrawberries)
int short = lot- numberStrawberries;
numberStrawberries=0;
}else{
//all out of strawberries
}

C# - Copy input from one textbox to another and vise versa

this is my first post and I'm fairly new to C#
I'm trying to create a Celsius to Fahrenheit converter and vise versa.
I have two textboxes, the user can either input a number into the Celsius textbox and the Fahrenheit will automatically be calculated and displayed into the Fahrenheit textbox or the user can input into the Fahrenheit and the Celsius value will be calculated and output.
Here is the code I have so far, this is a WFA.
private void txtCelsius_TextChanged(object sender, EventArgs e)
{
///*
if(string.IsNullOrEmpty(txtCelsius.Text))
{
txtFahrenheit.Clear();
return;
}
txtFahrenheit.Text = ((double.Parse(txtCelsius.Text)) * 1.8 + 32).ToString();
//*/
}
private void txtFahrenheit_TextChanged_1(object sender, EventArgs e)
{
///*
if (string.IsNullOrEmpty(txtFahrenheit.Text))
{
txtCelsius.Clear();
return;
}
txtCelsius.Text = ((double.Parse(txtFahrenheit.Text)) / 1.8 - 32).ToString();
//*/
}
Clearly, when I run this and input a value into either one of the textbox it will create an infinite loop. If I comment one or the other out it works for the other one.
Can someone help? Is there a way I can do something like the following pseudocode.
if textbox1 is getting input
textbox2.input = disabled
do calculations and display
if textbox2 is getting input
textbox1.input = disabled
do calculations and display
If tried searching for a solution but finding it hard to word what I'm looking for and coming up with no solutions.
PS. I keep seeing this in other posts, this is not homework, I'm just trying to come up with small programs to learn.
You are getting into an infinite loop because each time you update the other text boxes value it's firing the TextChanged event. To handle this add a variable to control when to update use TextChanged code.
bool _updating = false;
private void txtCelsius_TextChanged(object sender, EventArgs e)
{
if (!_updating)
{
try
{
_updating = true;
///*
if(string.IsNullOrEmpty(txtCelsius.Text))
{
txtFahrenheit.Clear();
return;
}
txtFahrenheit.Text = ((double.Parse(txtCelsius.Text)) * 1.8 + 32).ToString();
//*/
}
finally
{
_updating = false;
}
}
}
private void txtFahrenheit_TextChanged_1(object sender, EventArgs e)
{
if (!_updating)
{
try
{
_updating = true;
///*
if (string.IsNullOrEmpty(txtFahrenheit.Text))
{
txtCelsius.Clear();
return;
}
txtCelsius.Text = ((double.Parse(txtFahrenheit.Text)) / 1.8 - 32).ToString();
//*/
}
finally
{
_updating = false;
}
}
}

How do I reset random number, count, text, and label with button click c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am using Visual C# 2013. I have a form and I am wondering how to make my "Clear" button reset/refresh the whole form to the same state when I first clicked start (random number generated at form load, counter, textbox, and a label). For a number guessing form so that a user can play it again. Thanks in advance. Code is :
{
int Answer; // declares the Answer variable outside button event
int Guesses = 0; // start counter outside button event
int UserGuess;
public frmGuess()
{ // generates random number outside button event so does not change on button click
InitializeComponent();
Random rand = new Random();
Answer = rand.Next(100) + 1; // makes it range 1 to 100
}
private void btnGuess_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtGuess.Text)) // input validation check to make sure not blank
{
MessageBox.Show("Please enter a whole number between 1 and 100", "Error!!");
return;
} //end if
if (txtGuess.Text != "") // if its not blank, check to make sure its a whole number with try-catch
{
try
{
UserGuess = int.Parse(txtGuess.Text);
}
catch
{
MessageBox.Show("Please enter a whole number between 1 and 100", "Error!!");
}
} // end if
else
UserGuess = int.Parse(txtGuess.Text); // variable assign and code run
Guesses ++;
if (UserGuess > Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too high, try again.";
Guesses++;
}
else if (UserGuess < Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too low, try again.";
Guesses++;
}
else
{
lblAnswer.Text = "Congratulations the answer was " + Answer + "!\nYou guessed the number in " + Guesses + " tries.\nTo play again click the clear button.";
} //end if
}
private void btnClear_Click(object sender, EventArgs e) // clears Answer label and Guess textbox
{
txtGuess.Text = "";
lblAnswer.Text = "";
}
private void btnExit_Click(object sender, EventArgs e) // closes window
{
this.Close();
}
}
Here is a screenshot when they have guessed the number! (I don't have enough rep to post an image yet) http://i.stack.imgur.com/hB9yV.png
First, you should put all of the "initialization to be reset" code into a method that can be shared by the constructor and the "Clear" button:
private void ResetForm()
{
txtGuess.Text = "";
lblAnswer.Text = "";
Random rand = new Random();
Answer = rand.Next(100) + 1;
Guesses = 0;
}
(aside: you can actually just initialize the rand object once, as a readonly member field of the class (it can even be static if you like)...but in this case creating a new Random object each time you want to choose a new number, though not the most elegant approach, will work fine).
Then, call that method from your constructor and from the Click event handler:
public frmGuess()
{
InitializeComponent();
ResetForm();
}
private void btnClear_Click(object sender, EventArgs e)
{
ResetForm();
}
By the way, your "Guess" button handler could use some work too:
private void btnGuess_Click(object sender, EventArgs e)
{
lblAnswer.Text = "";
if (string.IsNullOrEmpty(txtGuess.Text)) // input validation check to make sure not blank
{
MessageBox.Show("Please enter a whole number between 1 and 100", "Error!!");
return;
} //end if
if (!int.TryParse(txtGuess.Text, out UserGuess))
{
MessageBox.Show("Please enter a whole number between 1 and 100", "Error!!");
return;
}
Guesses ++;
if (UserGuess > Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too high, try again.";
}
else if (UserGuess < Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too low, try again.";
}
else
{
lblAnswer.Text = "Congratulations the answer was " + Answer + "!\nYou guessed the number in " + Guesses + " tries.\nTo play again click the clear button.";
} //end if
}
The above removes some redundant code, fixes at least one bug, and gets rid of the need for exception handling.
EDIT
First, check out if you didn't drop brackets around if (txtGuess.Text != "") ... else(here) first.
private void btnClear_Click(object sender, EventArgs e) // clears Answer label and Guess textbox
{
txtGuess.Text = ""; // to reset the TextBox
lblAnswer.Text = ""; // to reset the Label
Random rand = new Random(); // Doesn't it make Answer to be always the same integer?
Answer = rand.Next(100) + 1; // to generate a new random answer
Guesses = 0; // to reset the number of guesses
}
Just try InitializeComponent(); inside the callback of Button_Click.
try reset control :
foreach (Control ctl in this.Controls)
{
ctl.ResetText();
}

C# Calculator with memory buttons

I am having some difficulties making my calculator have the ability to store values. The calculator works for everything except this and I am quite stuck. I think I might have to declare some constants or something that I am missing right now. I am super new at this and appreciate the help. Here is my code. Thanks for any help guys. Right now I am getting no errors but nothing works either! I am also supposed to make it so a "M" appears in a textbox when there is a value stored in memory but I figured it was easier to start with this part.
private void digitCalculate_Click(object sender, EventArgs e)
{
Button ButtonThatWasPushed = (Button)sender;
string ButtonText = ButtonThatWasPushed.Text;
decimal EndResult = 0;
decimal MemoryStore = 0;
if (ButtonText == "MC")
{
//Memory Clear
MemoryStore = 0;
return;
}
if (ButtonText == "MR")
{
//Memory Recall
txtDisplay.Text = MemoryStore.ToString();
return;
}
if (ButtonText == "MS")
{
// Memory subtract
MemoryStore -= EndResult;
return;
}
if (ButtonText == "M+")
{
// Memory add
MemoryStore += EndResult;
return;
}
}
You need to have Form level variable for decimal MemoryStore = 0; , since you have function level variable it will initialized to 0 when you click on digitCalculate button
decimal MemoryStore = 0;
decimal EndResult = 0;
public Form1()
{
InitializeComponent();
}
private void digitCalculate_Click(object sender, EventArgs e)
{
Button ButtonThatWasPushed = (Button)sender;
string ButtonText = ButtonThatWasPushed.Text;
//decimal EndResult = 0;
//decimal MemoryStore = 0;
And also note that
MC = Memory Clear sets the memory to 0
MR = Memory Recall uses the
number in memory
MS = Memory Store puts the number on the display into the memory
You nee to change "MS" logic and add "M-"
if (ButtonText == "MS")
{
MemoryStore = Decimal.Parse(txtDisplay.Text);
return;
}
if (ButtonText == "M-")
{
// Memory subtract
MemoryStore -= EndResult;
txtDisplay.Text = MemoryStore.ToString();
return;
}
if (ButtonText == "M+")
{
// Memory add
MemoryStore += EndResult;
txtDisplay.Text = MemoryStore.ToString();
return;
}
Just change the variable MemoryStore to a global variable. At the moment, it is being re-declared each time a button is pushed, meaning that the data is lost between button presses. Move it outside of the function, and it should work fine.

Event located immediately after DataSource Update from ActiveEditor in Grid

What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid. I need to run this calculation After the value in one of the dependent cells is changed, but only if the value was a Valid entry. The EditValueChanged, Validating, and Validated events of the editor/repository all occur before the data is posted back into the datasource. I am wondering if there is any event I can hook into that will allow me to fire this calculation after the data has been post back into the datasource, but before control is returned to the user.
Sample Code
//calculation functions
private void SetCalcROP(MyObjectt Row)
{
//rop = m/hr
TimeSpan ts = Row.ToTime - Row.FromTime;
double diffDepth = Row.EndDepth - Row.StartDepth;
if (ts.TotalHours > 0)//donot divide by 0
Row.ROP = diffDepth / ts.TotalHours;
else
Row.ROP = 0;
}
private void SetCalcDeltaP(MyObject Row)
{
Row.DeltaPress = Row.SPPOnBtm - Row.SPPOffBtm;
}
//events
private void repNumberInput_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colSPPOff) || vwDDJournal.FocusedColumn.Equals(colSPPOn))
SetCalcDeltaP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colStartDepth) || vwDDJournal.FocusedColumn.Equals(colEndDepth))
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repTimeEdit_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (string.IsNullOrEmpty(TE.Text))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column may not be blank");
return;
}
else
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repNumberInput_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (!string.IsNullOrEmpty(TE.Text))
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repTimeEdit_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (vwDDJournal.FocusedColumn.Equals(colToTime))
{//dont bother to check from time
//TIME TRAVEL CHECK!!!!
DateTime FromTime = Convert.ToDateTime(vwDDJournal.GetRowCellValue(vwDDJournal.FocusedRowHandle, colFromTime));
TimeEdit te = sender as TimeEdit;
DateTime ToTime = Convert.ToDateTime(te.EditValue);
if (ToTime < FromTime)
{//TIME TRAVEL
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "To Time must be greater than From Time");
return;
}
}
}
the problem is that everywhere I call this from, and whether I use vwDDJournal.GetRowCellValue(...) or vwDDJournal.GetFocusedRow() as MyObject, I still get the old edit value.
Requirements
I have to have the input validated before running the calculation.
I have to run the calculation immediately after making the change.
... What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid.
The best way to accomplish this task is using Unbound Columns feature.
The following example demonstrates how to implement this feature by handling the ColumnView.CustomUnboundColumnData event:
// Provides data for the Total column.
void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e) {
if (e.Column.FieldName == "Total" && e.IsGetData) e.Value =
getTotalValue(e.ListSourceRowIndex);
}
// Returns the total amount for a specific row.
decimal getTotalValue(int listSourceRowIndex) {
DataRow row = nwindDataSet.Tables["Order Details"].Rows[listSourceRowIndex];
decimal unitPrice = Convert.ToDecimal(row["UnitPrice"]);
decimal quantity = Convert.ToDecimal(row["Quantity"]);
decimal discount = Convert.ToDecimal(row["Discount"]);
return unitPrice * quantity * (1 - discount);
}
Original example: How to: Add an Unbound Column Storing Arbitrary Data
You can also implement calculated value for unbound column using expressions:
GridColumn columnTotal = new GridColumn();
columnTotal.FieldName = "Total";
columnTotal.Caption = "Total";
columnTotal.UnboundType = DevExpress.Data.UnboundColumnType.Decimal;
columnTotal.UnboundExpression = "[Quantity] * [UnitPrice] * (1 - [Discount])";
gridView1.Columns.Add(columnTotal);
How about CustomCellValue?
After posting back to the data source refresh the data.
It's called whenever data is updated or view is changed.

Categories